[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6EN0RZP4R3BYMF4FNZ7NM5J":3,"skill-same:01M6EN0RZP4R3BYMF4FNZ7NM5J":93},{"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":43,"linkOnly":44,"markdownContent":45,"markdownBody":46,"frontMatter":47,"refName":48,"commitSha":49,"skillDirectory":50,"forksCount":51,"repositoryHtmlUrl":52,"repositoryHomepageUrl":53,"ownerHtmlUrl":54,"ownerBlogUrl":6,"ownerDescription":55,"updatedAt":56,"install":57,"resources":70},"01M6EN0RZP4R3BYMF4FNZ7NM5J","auth",null,"Authentication and access control skill for Next.js 15 + Supabase applications. Use when implementing user authentication, protecting routes, managing user sessions, enforcing role-based access control (admin\u002Fmember), or working with multi-tenant family-based data isolation. Covers login\u002Flogout, registration with email verification, OAuth (GitHub), route protection for Server Components and Server Actions, admin-only features, and multi-tenant data access patterns.","ComeOnOliver\u002Fskillshub","ComeOnOliver","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F43215937?v=4","01M6E5JNFECJAAVFE0W7SMWWD2","Haoran Shu","01M6E5JNNDQS7AJZDYFQ8TPZCK",67,"MIT","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Faiskillstore\u002Fmarketplace\u002Fbom-98\u002Fauth\u002FSKILL.md",[18],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000023","Skill与智能体开发","SCENARIO","使用场景",[5,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42],"applications","isolation","Access Control","next","route","family","patterns","registration","only","access","components","data","email","actions","server","supabase","verification","authentication","sessions","2026-11-10 10:12:30",false,"---\nname: auth\ndescription: Authentication and access control skill for Next.js 15 + Supabase applications. Use when implementing user authentication, protecting routes, managing user sessions, enforcing role-based access control (admin\u002Fmember), or working with multi-tenant family-based data isolation. Covers login\u002Flogout, registration with email verification, OAuth (GitHub), route protection for Server Components and Server Actions, admin-only features, and multi-tenant data access patterns.\n---\n\n# Authentication & Access Control\n\nThis skill provides workflows for implementing authentication and access control in this Next.js 15 + Supabase application using server-side auth with httpOnly cookies, hybrid route protection, and multi-tenant family-based data isolation.\n\n## System Overview\n\n- **Auth Provider**: Supabase Auth with httpOnly cookies\n- **Architecture**: Next.js 15 App Router with Server Components and Server Actions\n- **Route Protection**: Hybrid approach (page-level auth checks, not middleware-only)\n- **Multi-Tenancy**: Family-based data isolation with RLS policies\n- **Roles**: Admin (first user in family) and Member\n\n## Core Workflows\n\n### Protecting a New Route\n\nTo protect a route from unauthenticated users:\n\n1. Import `requireAuthRedirect` from `@\u002Flib\u002Fauth\u002Fserver-auth`\n2. Call `await requireAuthRedirect()` at the start of the component\n3. User will be redirected to `\u002Flogin` if not authenticated\n\n```typescript\nimport { requireAuthRedirect } from '@\u002Flib\u002Fauth\u002Fserver-auth';\n\nexport default async function ProtectedPage() {\n  await requireAuthRedirect();\n\n  \u002F\u002F User guaranteed authenticated here\n  return \u003CYourContent \u002F>;\n}\n```\n\nTo protect an entire route group, add this to the layout component. All child routes will inherit the protection.\n\n### Protecting a Server Action\n\nTo require authentication in a Server Action:\n\n1. Import `requireAuth` from `@\u002Flib\u002Fauth\u002Fserver-auth`\n2. Call `const user = await requireAuth()` at the start of the action\n3. Action will throw `UnauthorizedError` if user not authenticated\n\n```typescript\n'use server';\nimport { requireAuth } from '@\u002Flib\u002Fauth\u002Fserver-auth';\n\nexport async function myAction() {\n  const user = await requireAuth();\n\n  \u002F\u002F Proceed with authenticated action\n}\n```\n\n### Getting Current User Data\n\n- `getCurrentUser()` - Auth user (email, id), returns null if not logged in\n- `getUserData()` - Extended profile (role, familyId, firstName, lastName, active)\n- `getCurrentFamilyId()` - Just the family ID\n\nAll use React `cache()` - multiple calls in same request return cached value.\n\n### Implementing Admin-Only Features\n\nTo restrict a page to admins:\n\n```typescript\nimport { requireAdminRedirect } from '@\u002Flib\u002Fauth\u002Fserver-auth';\n\nexport default async function AdminPage() {\n  await requireAdminRedirect();\n\n  \u002F\u002F User guaranteed to be admin\n  return \u003CAdminPanel \u002F>;\n}\n```\n\nTo restrict a Server Action to admins:\n\n```typescript\n'use server';\nimport { requireAdmin } from '@\u002Flib\u002Fauth\u002Fserver-auth';\n\nexport async function adminAction() {\n  await requireAdmin(); \u002F\u002F Throws if not admin\n  \u002F\u002F Proceed\n}\n```\n\nTo conditionally show admin UI:\n\n```typescript\nimport { isAdmin } from '@\u002Flib\u002Fauth\u002Fserver-auth';\n\nexport default async function Page() {\n  const userIsAdmin = await isAdmin();\n\n  return (\n    \u003C>\n      \u003CRegularContent \u002F>\n      {userIsAdmin && \u003CAdminControls \u002F>}\n    \u003C\u002F>\n  );\n}\n```\n\n### Enforcing Multi-Tenant Data Access\n\nTo ensure users only access their own family's data:\n\n```typescript\n'use server';\nimport { requireFamilyAccess } from '@\u002Flib\u002Fauth\u002Fserver-auth';\n\nexport async function updateFamilyData(familyId: string, data: any) {\n  await requireFamilyAccess(familyId); \u002F\u002F Throws if user not in this family\n\n  \u002F\u002F User guaranteed to belong to this family\n  await updateDatabase(familyId, data);\n}\n```\n\nWhen fetching current user's family data, use `getCurrentFamilyId()` instead - no need for `requireFamilyAccess` since it's their own family.\n\n### Adding a New Authentication Page\n\nTo create a new auth page (login, register, password reset):\n\n1. Create page under `src\u002Fapp\u002F(auth)\u002Fpage-name\u002F`\n2. The `(auth)` group layout automatically redirects authenticated users to `\u002Fdashboard`\n3. Create corresponding Server Action in `actions.ts` file\n4. Import and use Supabase client: `const supabase = await createClient()`\n\nPages in `(auth)` group are automatically protected from authenticated users - they'll be redirected to dashboard if already logged in.\n\n### Implementing Login\u002FLogout\n\nUse `supabase.auth.signInWithPassword()` for login and `supabase.auth.signOut()` for logout. See `references\u002Fpatterns.md` for complete code examples.\n\n### Adding OAuth Providers\n\n1. Enable provider in Supabase Dashboard\n2. Use `supabase.auth.signInWithOAuth({ provider: 'github', options: {...} })`\n3. Callback handled automatically by `src\u002Fapp\u002Fauth\u002Fcallback\u002Froute.ts`\n\nSee `references\u002Fpatterns.md` for full implementation examples.\n\n## Security Requirements\n\n### Token Validation\n- Always use `supabase.auth.getUser()` to validate tokens (revalidates with server)\n- Never use `supabase.auth.getSession()` in server code (can be spoofed)\n\n### Server-Side Only\n- All auth helpers in `src\u002Flib\u002Fauth\u002Fserver-auth.ts` are server-side only\n- Never import these in Client Components\n- Never add `'use server'` directive to `server-auth.ts` (breaks class exports)\n\n### Middleware\n- Middleware automatically refreshes tokens on every request\n- Uses `updateSession()` from `src\u002Flib\u002Fsupabase\u002Fmiddleware.ts`\n- Calls `getUser()` to revalidate tokens\n- No additional token refresh logic needed\n\n## Reference Files\n\nFor detailed information, see:\n- `references\u002Ffile-tree.md` - Complete file structure and organization\n- `references\u002Fsecurity.md` - Security best practices and requirements\n- `references\u002Fpatterns.md` - Code examples and common patterns\n- `references\u002Fflows.md` - Authentication flow diagrams\n\n## Quick Reference\n\n**Key Files**: `src\u002Flib\u002Fauth\u002Fserver-auth.ts` (helpers), `src\u002Fmiddleware.ts` (token refresh), `src\u002Fapp\u002Fdashboard\u002Flayout.tsx` (dashboard protection)\n\n**Environment**: `NEXT_PUBLIC_SUPABASE_URL`, `NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY`, `NEXT_PUBLIC_SITE_URL`\n\n**Database**: `auth.users` (Supabase auth), `public.families` (households), `public.users` (profiles)\n\n## Common Issues\n\n**'use server' export error**: Remove `'use server'` from `server-auth.ts` - these are utilities, not actions\n\n**Middleware redirect fails**: Use `requireAuth()` in Server Actions - middleware redirects don't work with POST\n\n**Multi-tenant access denied**: Use `requireFamilyAccess(familyId)` to validate family ownership\n","# Authentication & Access Control\n\nThis skill provides workflows for implementing authentication and access control in this Next.js 15 + Supabase application using server-side auth with httpOnly cookies, hybrid route protection, and multi-tenant family-based data isolation.\n\n## System Overview\n\n- **Auth Provider**: Supabase Auth with httpOnly cookies\n- **Architecture**: Next.js 15 App Router with Server Components and Server Actions\n- **Route Protection**: Hybrid approach (page-level auth checks, not middleware-only)\n- **Multi-Tenancy**: Family-based data isolation with RLS policies\n- **Roles**: Admin (first user in family) and Member\n\n## Core Workflows\n\n### Protecting a New Route\n\nTo protect a route from unauthenticated users:\n\n1. Import `requireAuthRedirect` from `@\u002Flib\u002Fauth\u002Fserver-auth`\n2. Call `await requireAuthRedirect()` at the start of the component\n3. User will be redirected to `\u002Flogin` if not authenticated\n\n```typescript\nimport { requireAuthRedirect } from '@\u002Flib\u002Fauth\u002Fserver-auth';\n\nexport default async function ProtectedPage() {\n  await requireAuthRedirect();\n\n  \u002F\u002F User guaranteed authenticated here\n  return \u003CYourContent \u002F>;\n}\n```\n\nTo protect an entire route group, add this to the layout component. All child routes will inherit the protection.\n\n### Protecting a Server Action\n\nTo require authentication in a Server Action:\n\n1. Import `requireAuth` from `@\u002Flib\u002Fauth\u002Fserver-auth`\n2. Call `const user = await requireAuth()` at the start of the action\n3. Action will throw `UnauthorizedError` if user not authenticated\n\n```typescript\n'use server';\nimport { requireAuth } from '@\u002Flib\u002Fauth\u002Fserver-auth';\n\nexport async function myAction() {\n  const user = await requireAuth();\n\n  \u002F\u002F Proceed with authenticated action\n}\n```\n\n### Getting Current User Data\n\n- `getCurrentUser()` - Auth user (email, id), returns null if not logged in\n- `getUserData()` - Extended profile (role, familyId, firstName, lastName, active)\n- `getCurrentFamilyId()` - Just the family ID\n\nAll use React `cache()` - multiple calls in same request return cached value.\n\n### Implementing Admin-Only Features\n\nTo restrict a page to admins:\n\n```typescript\nimport { requireAdminRedirect } from '@\u002Flib\u002Fauth\u002Fserver-auth';\n\nexport default async function AdminPage() {\n  await requireAdminRedirect();\n\n  \u002F\u002F User guaranteed to be admin\n  return \u003CAdminPanel \u002F>;\n}\n```\n\nTo restrict a Server Action to admins:\n\n```typescript\n'use server';\nimport { requireAdmin } from '@\u002Flib\u002Fauth\u002Fserver-auth';\n\nexport async function adminAction() {\n  await requireAdmin(); \u002F\u002F Throws if not admin\n  \u002F\u002F Proceed\n}\n```\n\nTo conditionally show admin UI:\n\n```typescript\nimport { isAdmin } from '@\u002Flib\u002Fauth\u002Fserver-auth';\n\nexport default async function Page() {\n  const userIsAdmin = await isAdmin();\n\n  return (\n    \u003C>\n      \u003CRegularContent \u002F>\n      {userIsAdmin && \u003CAdminControls \u002F>}\n    \u003C\u002F>\n  );\n}\n```\n\n### Enforcing Multi-Tenant Data Access\n\nTo ensure users only access their own family's data:\n\n```typescript\n'use server';\nimport { requireFamilyAccess } from '@\u002Flib\u002Fauth\u002Fserver-auth';\n\nexport async function updateFamilyData(familyId: string, data: any) {\n  await requireFamilyAccess(familyId); \u002F\u002F Throws if user not in this family\n\n  \u002F\u002F User guaranteed to belong to this family\n  await updateDatabase(familyId, data);\n}\n```\n\nWhen fetching current user's family data, use `getCurrentFamilyId()` instead - no need for `requireFamilyAccess` since it's their own family.\n\n### Adding a New Authentication Page\n\nTo create a new auth page (login, register, password reset):\n\n1. Create page under `src\u002Fapp\u002F(auth)\u002Fpage-name\u002F`\n2. The `(auth)` group layout automatically redirects authenticated users to `\u002Fdashboard`\n3. Create corresponding Server Action in `actions.ts` file\n4. Import and use Supabase client: `const supabase = await createClient()`\n\nPages in `(auth)` group are automatically protected from authenticated users - they'll be redirected to dashboard if already logged in.\n\n### Implementing Login\u002FLogout\n\nUse `supabase.auth.signInWithPassword()` for login and `supabase.auth.signOut()` for logout. See `references\u002Fpatterns.md` for complete code examples.\n\n### Adding OAuth Providers\n\n1. Enable provider in Supabase Dashboard\n2. Use `supabase.auth.signInWithOAuth({ provider: 'github', options: {...} })`\n3. Callback handled automatically by `src\u002Fapp\u002Fauth\u002Fcallback\u002Froute.ts`\n\nSee `references\u002Fpatterns.md` for full implementation examples.\n\n## Security Requirements\n\n### Token Validation\n- Always use `supabase.auth.getUser()` to validate tokens (revalidates with server)\n- Never use `supabase.auth.getSession()` in server code (can be spoofed)\n\n### Server-Side Only\n- All auth helpers in `src\u002Flib\u002Fauth\u002Fserver-auth.ts` are server-side only\n- Never import these in Client Components\n- Never add `'use server'` directive to `server-auth.ts` (breaks class exports)\n\n### Middleware\n- Middleware automatically refreshes tokens on every request\n- Uses `updateSession()` from `src\u002Flib\u002Fsupabase\u002Fmiddleware.ts`\n- Calls `getUser()` to revalidate tokens\n- No additional token refresh logic needed\n\n## Reference Files\n\nFor detailed information, see:\n- `references\u002Ffile-tree.md` - Complete file structure and organization\n- `references\u002Fsecurity.md` - Security best practices and requirements\n- `references\u002Fpatterns.md` - Code examples and common patterns\n- `references\u002Fflows.md` - Authentication flow diagrams\n\n## Quick Reference\n\n**Key Files**: `src\u002Flib\u002Fauth\u002Fserver-auth.ts` (helpers), `src\u002Fmiddleware.ts` (token refresh), `src\u002Fapp\u002Fdashboard\u002Flayout.tsx` (dashboard protection)\n\n**Environment**: `NEXT_PUBLIC_SUPABASE_URL`, `NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY`, `NEXT_PUBLIC_SITE_URL`\n\n**Database**: `auth.users` (Supabase auth), `public.families` (households), `public.users` (profiles)\n\n## Common Issues\n\n**'use server' export error**: Remove `'use server'` from `server-auth.ts` - these are utilities, not actions\n\n**Middleware redirect fails**: Use `requireAuth()` in Server Actions - middleware redirects don't work with POST\n\n**Multi-tenant access denied**: Use `requireFamilyAccess(familyId)` to validate family ownership\n",{"name":5,"description":7},"main","def8531e65114c0fca8fb8551c1871ee0eed705c","skills\u002Faiskillstore\u002Fmarketplace\u002Fbom-98\u002Fauth",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":58,"prompt":68,"zipAvailable":69},[59,62,65],{"tool":60,"command":61},"npx","npx skills add ComeOnOliver\u002Fskillshub --skill auth",{"tool":63,"command":64},"bunx","bunx skills add ComeOnOliver\u002Fskillshub --skill auth",{"tool":66,"command":67},"pnpm","pnpm dlx skills add ComeOnOliver\u002Fskillshub --skill auth","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Faiskillstore\u002Fmarketplace\u002Fbom-98\u002Fauth\u002FSKILL.md",true,[71,77,81,85,89],{"path":72,"resourceType":73,"resourceTypeDesc":74,"sizeBytes":75,"sourceHtmlUrl":76},"references\u002Ffile-tree.md","REFERENCE","参考文档",3134,"https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Faiskillstore\u002Fmarketplace\u002Fbom-98\u002Fauth\u002Freferences\u002Ffile-tree.md",{"path":78,"resourceType":73,"resourceTypeDesc":74,"sizeBytes":79,"sourceHtmlUrl":80},"references\u002Fflows.md",6954,"https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Faiskillstore\u002Fmarketplace\u002Fbom-98\u002Fauth\u002Freferences\u002Fflows.md",{"path":82,"resourceType":73,"resourceTypeDesc":74,"sizeBytes":83,"sourceHtmlUrl":84},"references\u002Fpatterns.md",6557,"https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Faiskillstore\u002Fmarketplace\u002Fbom-98\u002Fauth\u002Freferences\u002Fpatterns.md",{"path":86,"resourceType":73,"resourceTypeDesc":74,"sizeBytes":87,"sourceHtmlUrl":88},"references\u002Fsecurity.md",3816,"https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Faiskillstore\u002Fmarketplace\u002Fbom-98\u002Fauth\u002Freferences\u002Fsecurity.md",{"path":90,"resourceType":73,"resourceTypeDesc":74,"sizeBytes":91,"sourceHtmlUrl":92},"skill-report.json",29167,"https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Faiskillstore\u002Fmarketplace\u002Fbom-98\u002Fauth\u002Fskill-report.json",[94,104,114,123,129,136],{"skillNo":95,"name":96,"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":97,"categories":98,"keywords":100,"publishedAt":43},"01M6FKJN13GMG4KY57J3QD8GY5","model-hierarchy-skill","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzscole\u002Fmodel-hierarchy-skill\u002Fmodel-hierarchy-skill\u002FSKILL.md",[99],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},[101,102,103],"model","model hierarchy","model hierarchy skill",{"skillNo":105,"name":106,"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":107,"categories":108,"keywords":110,"publishedAt":43},"01M6FKJJJ6GCAMR4PPPRD12M5X","zoom-mcp","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fzoom-mcp\u002FSKILL.md",[109],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},[111,112,113],"MCP","zoom","zoom mcp",{"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":43},"01M6FKJE3KYT3KPEZMEEHYKA6K","zoom-apps-sdk","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fzoom-apps-sdk\u002FSKILL.md",[],[120,121,122,112],"sdk","zoom apps sdk","apps",{"skillNo":124,"name":125,"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":126,"categories":127,"keywords":128,"publishedAt":43},"01M6FKJ9EDH9Q5VWDF8HAJRSP0","windows","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fwindows\u002FSKILL.md",[],[125],{"skillNo":130,"name":131,"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":132,"categories":133,"keywords":135,"publishedAt":43},"01M6FKJ666BEEFC3AE9GJ72Q93","whiteboard","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fwhiteboard\u002FSKILL.md",[134],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},[131],{"skillNo":137,"name":138,"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":139,"categories":140,"keywords":141,"publishedAt":43},"01M6FKJ21WFCDGTJQ2Q91T9DVW","websockets","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fwebsockets\u002FSKILL.md",[],[138]]