[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6EBNGRCT136EETTNFPADF60":3,"skill-same:01M6EBNGRCT136EETTNFPADF60":69},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":23,"publishedAt":41,"linkOnly":42,"markdownContent":43,"markdownBody":44,"frontMatter":45,"refName":46,"commitSha":47,"skillDirectory":48,"forksCount":49,"repositoryHtmlUrl":50,"repositoryHomepageUrl":51,"ownerHtmlUrl":52,"ownerBlogUrl":6,"ownerDescription":53,"updatedAt":54,"install":55,"resources":68},"01M6EBNGRCT136EETTNFPADF60","nextjs-server-actions",null,"Mutations, Form handling, and RPC-style calls. Use when implementing Server Actions, form mutations, or RPC-style data mutations in Next.js. (triggers: app\u002F**\u002Factions.ts, src\u002Fapp\u002F**\u002Factions.ts, app\u002F**\u002F*.tsx, src\u002Fapp\u002F**\u002F*.tsx, use server, Server Action, revalidatePath, useFormStatus)","ComeOnOliver\u002Fskillshub","ComeOnOliver","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F43215937?v=4","01M6E5JNFECJAAVFE0W7SMWWD2","Haoran Shu","01M6E5JNNDQS7AJZDYFQ8TPZCK",66,"MIT","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002FHoangNguyen0403\u002Fagent-skills-standard\u002Fnextjs-server-actions\u002FSKILL.md",[18],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000010","后端与接口","SCENARIO","使用场景",[24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40],"server","nextjs server actions","nextjs","actions","data","Next.js","js","src","use","tsx","mutations","next","triggers","app","style","form","rpc","2026-11-10 10:12:30",false,"---\nname: nextjs-server-actions\ndescription: 'Mutations, Form handling, and RPC-style calls. Use when implementing Server Actions, form mutations, or RPC-style data mutations in Next.js. (triggers: app\u002F**\u002Factions.ts, src\u002Fapp\u002F**\u002Factions.ts, app\u002F**\u002F*.tsx, src\u002Fapp\u002F**\u002F*.tsx, use server, Server Action, revalidatePath, useFormStatus)'\n---\n\n# Server Actions\n\n## **Priority: P1 (HIGH)**\n\n> [!WARNING]\n> If the project uses the `pages\u002F` directory instead of the App Router, **ignore** this skill entirely.\n\nHandle form submissions and mutations without creating API endpoints.\n\n## Implementation Guidelines\n\n- **Directive**: Always start the file or function with `'use server'`. Access `formData.get('title')` for typed form fields. Export async functions for mutations.\n- **Form Handling**: Use the `action` prop of `\u003Cform>` to trigger actions via `action={createPost}`. Use `useFormStatus()` for `pending` states — `disabled={pending}` on buttons. Use `useActionState` (React 19\u002FNext.js 15) for `action={action}` form state with `\u003Cform action={action}>`.\n- **Data Refresh**: Trigger UI updates using **`revalidatePath('\u002F')`** or **`revalidateTag('tag-name')`** after a successful mutation.\n- **Interactivity**: For non-form triggers, invoke actions using the **`useTransition`** hook to handle loading UI and prevent the page from blocking.\n- **Optimistic Updates**: Use **`useOptimistic`** to show the expected UI state immediately before the server confirms the mutation.\n- **Security**: **Sanitize all inputs** from `FormData`. Perform **auth checks** inside every action (`await auth()`). Limit file uploads by size and MIME type.\n\n- **Form**: `\u003Cform action={createPost}>` (Progressive enhancements work without JS).\n- **Event Handler**: `onClick={() => createPost(data)}`.\n- **Pending State**: Use `useFormStatus` hook (must be inside a component rendered within the form).\n\n## **P1: Operational Standard**\n\n### **1. Secure & Validate**\n\nAlways validate inputs with `z.object({` schema and `safeParse` before processing. Check authorization within the action. See [Secure Action Example](references\u002Fsecure-actions.md).\n\n### **2. Pending States**\n\nUse `useActionState` (React 19\u002FNext.js 15+) for state handling and `useFormStatus` for button loading states.\n\n## **Constraints**\n\n- **Closures**: Avoid defining actions inside components to prevent hidden closure encryption overhead and serialization bugs.\n- **Redirection**: Use `redirect()` for success navigation; it throws an error that Next.js catches to handle the redirect.\n\n## Anti-Patterns\n\n- **No unvalidated Server Action inputs**: Always validate with Zod before processing.\n- **No skipped auth checks**: Verify session\u002Fuser inside every action, not just middleware.\n- **No actions defined inside components**: Define in `actions.ts` to avoid closure bugs.\n- **No `redirect()` in try\u002Fcatch**: `redirect()` throws; catching it suppresses the redirect.\n\n","# Server Actions\n\n## **Priority: P1 (HIGH)**\n\n> [!WARNING]\n> If the project uses the `pages\u002F` directory instead of the App Router, **ignore** this skill entirely.\n\nHandle form submissions and mutations without creating API endpoints.\n\n## Implementation Guidelines\n\n- **Directive**: Always start the file or function with `'use server'`. Access `formData.get('title')` for typed form fields. Export async functions for mutations.\n- **Form Handling**: Use the `action` prop of `\u003Cform>` to trigger actions via `action={createPost}`. Use `useFormStatus()` for `pending` states — `disabled={pending}` on buttons. Use `useActionState` (React 19\u002FNext.js 15) for `action={action}` form state with `\u003Cform action={action}>`.\n- **Data Refresh**: Trigger UI updates using **`revalidatePath('\u002F')`** or **`revalidateTag('tag-name')`** after a successful mutation.\n- **Interactivity**: For non-form triggers, invoke actions using the **`useTransition`** hook to handle loading UI and prevent the page from blocking.\n- **Optimistic Updates**: Use **`useOptimistic`** to show the expected UI state immediately before the server confirms the mutation.\n- **Security**: **Sanitize all inputs** from `FormData`. Perform **auth checks** inside every action (`await auth()`). Limit file uploads by size and MIME type.\n\n- **Form**: `\u003Cform action={createPost}>` (Progressive enhancements work without JS).\n- **Event Handler**: `onClick={() => createPost(data)}`.\n- **Pending State**: Use `useFormStatus` hook (must be inside a component rendered within the form).\n\n## **P1: Operational Standard**\n\n### **1. Secure & Validate**\n\nAlways validate inputs with `z.object({` schema and `safeParse` before processing. Check authorization within the action. See [Secure Action Example](references\u002Fsecure-actions.md).\n\n### **2. Pending States**\n\nUse `useActionState` (React 19\u002FNext.js 15+) for state handling and `useFormStatus` for button loading states.\n\n## **Constraints**\n\n- **Closures**: Avoid defining actions inside components to prevent hidden closure encryption overhead and serialization bugs.\n- **Redirection**: Use `redirect()` for success navigation; it throws an error that Next.js catches to handle the redirect.\n\n## Anti-Patterns\n\n- **No unvalidated Server Action inputs**: Always validate with Zod before processing.\n- **No skipped auth checks**: Verify session\u002Fuser inside every action, not just middleware.\n- **No actions defined inside components**: Define in `actions.ts` to avoid closure bugs.\n- **No `redirect()` in try\u002Fcatch**: `redirect()` throws; catching it suppresses the redirect.\n\n",{"name":5,"description":7},"main","def8531e65114c0fca8fb8551c1871ee0eed705c","skills\u002FHoangNguyen0403\u002Fagent-skills-standard\u002Fnextjs-server-actions",24,"https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub","https:\u002F\u002Fskillshub.wtf","https:\u002F\u002Fgithub.com\u002FComeOnOliver","AI & Blockchain Engineer\r\n","2026-06-24 22:07:19",{"source":8,"skillName":5,"commands":56,"prompt":66,"zipAvailable":67},[57,60,63],{"tool":58,"command":59},"npx","npx skills add ComeOnOliver\u002Fskillshub --skill nextjs-server-actions",{"tool":61,"command":62},"bunx","bunx skills add ComeOnOliver\u002Fskillshub --skill nextjs-server-actions",{"tool":64,"command":65},"pnpm","pnpm dlx skills add ComeOnOliver\u002Fskillshub --skill nextjs-server-actions","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002FHoangNguyen0403\u002Fagent-skills-standard\u002Fnextjs-server-actions\u002FSKILL.md",true,[],[70,82,92,101,107,114],{"skillNo":71,"name":72,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":73,"categories":74,"keywords":78,"publishedAt":41},"01M6FKJN13GMG4KY57J3QD8GY5","model-hierarchy-skill","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzscole\u002Fmodel-hierarchy-skill\u002Fmodel-hierarchy-skill\u002FSKILL.md",[75],{"categoryNo":76,"categoryName":77,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000023","Skill与智能体开发",[79,80,81],"model","model hierarchy","model hierarchy skill",{"skillNo":83,"name":84,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":85,"categories":86,"keywords":88,"publishedAt":41},"01M6FKJJJ6GCAMR4PPPRD12M5X","zoom-mcp","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fzoom-mcp\u002FSKILL.md",[87],{"categoryNo":76,"categoryName":77,"taxonomyType":21,"taxonomyTypeDesc":22},[89,90,91],"MCP","zoom","zoom mcp",{"skillNo":93,"name":94,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":95,"categories":96,"keywords":97,"publishedAt":41},"01M6FKJE3KYT3KPEZMEEHYKA6K","zoom-apps-sdk","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fzoom-apps-sdk\u002FSKILL.md",[],[98,99,100,90],"sdk","zoom apps sdk","apps",{"skillNo":102,"name":103,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":104,"categories":105,"keywords":106,"publishedAt":41},"01M6FKJ9EDH9Q5VWDF8HAJRSP0","windows","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fwindows\u002FSKILL.md",[],[103],{"skillNo":108,"name":109,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":110,"categories":111,"keywords":113,"publishedAt":41},"01M6FKJ666BEEFC3AE9GJ72Q93","whiteboard","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fwhiteboard\u002FSKILL.md",[112],{"categoryNo":76,"categoryName":77,"taxonomyType":21,"taxonomyTypeDesc":22},[109],{"skillNo":115,"name":116,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":117,"categories":118,"keywords":119,"publishedAt":41},"01M6FKJ21WFCDGTJQ2Q91T9DVW","websockets","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fwebsockets\u002FSKILL.md",[],[116]]