Skip to content

Implement SkillStudio app with local storage safety and Vercel AI SDK v5 - #1

Merged
ivancidev merged 4 commits into
mainfrom
feat/client-key-security
Jul 14, 2026
Merged

Implement SkillStudio app with local storage safety and Vercel AI SDK v5#1
ivancidev merged 4 commits into
mainfrom
feat/client-key-security

Conversation

@ivancidev

Copy link
Copy Markdown
Owner

This pull request adds comprehensive reference documentation for accessibility and Bun usage, as well as a WCAG 2.2 quick reference guide. These additions provide practical code patterns, standards checklists, and decision guidance to support accessible and efficient JavaScript/TypeScript development.

Accessibility Reference Additions:

  • Practical accessibility code patterns for common UI requirements (e.g., modal focus trap, skip links, ARIA tabs, error handling) were added in .agents/skills/accessibility/references/A11Y-PATTERNS.md to serve as ready-to-use examples for developers.
  • A WCAG 2.2 quick reference was introduced in .agents/skills/accessibility/references/WCAG.md, summarizing success criteria by level, ARIA patterns, recent changes from WCAG 2.1 to 2.2, and recommended accessibility testing tools.

Bun Reference Addition:

  • A new skill reference for Bun was added in .agents/skills/bun/SKILL.md, covering product overview, essential commands, configuration, workflow steps, common pitfalls, and a verification checklist to streamline Bun adoption for JavaScript/TypeScript projects.…safety and Vercel AI SDK v5

@ivancidev ivancidev self-assigned this Jul 14, 2026
Copilot AI review requested due to automatic review settings July 14, 2026 03:14

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot wasn't able to review this pull request because it exceeds the maximum number of lines (20,000). Try reducing the number of changed lines and requesting a review from Copilot again.

@qodo-code-review

qodo-code-review Bot commented Jul 14, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (3) 📘 Rule violations (5) 📎 Requirement gaps (0) 🎨 UX issues (0) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)

Grey Divider


Action required

1. skill-card-grid uses gradients 📘 Rule violation ⚙ Maintainability
Description
The .skill-card-grid background is built with linear-gradient(...), which violates the
design-system rule forbidding any CSS gradient usage. This can cause repeated visual regressions
against the strict SkillStudio styling constraints.
Code

app/globals.css[R29-34]

+/* Custom grid background for signature cards */
+.skill-card-grid {
+  background-image: 
+    linear-gradient(rgba(99, 102, 241, 0.06) 1px, transparent 1px),
+    linear-gradient(90deg, rgba(99, 102, 241, 0.06) 1px, transparent 1px);
+  background-size: 24px 24px;
Evidence
PR Compliance ID 5 explicitly forbids any CSS gradients. The new .skill-card-grid style uses
linear-gradient(...) twice to construct the background grid.

AGENTS.md: Follow SkillStudio Design System Styling Constraints (Colors, Backgrounds, Typography, No Gradients): AGENTS.md: Follow SkillStudio Design System Styling Constraints (Colors, Backgrounds, Typography, No Gradients): AGENTS.md: Follow SkillStudio Design System Styling Constraints (Colors, Backgrounds, Typography, No Gradients): AGENTS.md: Follow SkillStudio Design System Styling Constraints (Colors, Backgrounds, Typography, No Gradients)
app/globals.css[29-34]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`app/globals.css` uses `linear-gradient(...)` to render the signature card grid, but the design system forbids any CSS gradients.
## Issue Context
The grid effect can be implemented without CSS gradients (e.g., using an SVG background image or a data-URI) while preserving the required `#6366F1` @ 6% opacity and `24px 24px` sizing.
## Fix Focus Areas
- app/globals.css[29-35]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Clear Keys uses rose accent 📘 Rule violation ⚙ Maintainability
Description
The Clear Keys button introduces rose colors (text-rose-600, border-rose-200,
hover:bg-rose-50), which violates the rule that #6366F1 is the single visual accent color. This
breaks the strict SkillStudio design system constraints.
Code

app/(app)/settings/page.tsx[R102-106]

+          <Button 
+            variant="secondary" 
+            onClick={handleClear} 
+            className="flex items-center gap-2 text-rose-600 border-rose-200 hover:bg-rose-50 hover:text-rose-700"
+          >
Evidence
PR Compliance ID 5 requires #6366F1 as the only accent color. The new button styling uses rose-*
utility classes, introducing an additional accent palette.

AGENTS.md: Follow SkillStudio Design System Styling Constraints (Colors, Backgrounds, Typography, No Gradients): AGENTS.md: Follow SkillStudio Design System Styling Constraints (Colors, Backgrounds, Typography, No Gradients): AGENTS.md: Follow SkillStudio Design System Styling Constraints (Colors, Backgrounds, Typography, No Gradients): AGENTS.md: Follow SkillStudio Design System Styling Constraints (Colors, Backgrounds, Typography, No Gradients)
app/(app)/settings/page.tsx[102-106]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
A non-indigo accent color (`rose-*`) is used for the destructive `Clear Keys` button.
## Issue Context
The design system requires `#6366F1` as the single visual accent (with `#22C55E` reserved only for positive/ready indicators). Destructive actions should still be represented using approved neutrals/indigo styling patterns.
## Fix Focus Areas
- app/(app)/settings/page.tsx[98-109]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Chat route uses any casts 📘 Rule violation ⚙ Maintainability
Description
app/api/chat/route.ts introduces multiple any casts and an error: any catch parameter without
any justification comment. This erases type safety and violates the strict TypeScript compliance
requirement.
Code

app/api/chat/route.ts[R24-36]

+    const model = getModelInstance(provider as ModelProvider, apiKey, modelName) as any
+
+    // Call streamText with automatic tool execution (up to 5 steps)
+    const result = streamText({
+      model,
+      system: SYSTEM_PROMPT,
+      messages,
+      tools: agentTools,
+      maxSteps: 5,
+    } as any)
+
+    return (result as any).toDataStreamResponse()
+  } catch (error: any) {
Evidence
PR Compliance ID 2 forbids introducing any unless justified and documented. The route casts the
model/result/options to any and uses catch (error: any) with no explanatory comment.

AGENTS.md: Enforce Strict TypeScript: Avoid 'any' Casts Unless Justified and Documented: AGENTS.md: Enforce Strict TypeScript: Avoid 'any' Casts Unless Justified and Documented: AGENTS.md: Enforce Strict TypeScript: Avoid 'any' Casts Unless Justified and Documented: AGENTS.md: Enforce Strict TypeScript: Avoid 'any' Casts Unless Justified and Documented
app/api/chat/route.ts[24-36]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The API route uses `as any` and `catch (error: any)` without documented necessity.
## Issue Context
Compliance requires avoiding `any` unless unavoidable and explicitly documented. This route can typically be typed by:
- Validating/parsing the JSON body (e.g., with Zod) into a concrete type
- Using `unknown` in catch and narrowing
- Avoiding `as any` around `streamText` options and the returned result
## Fix Focus Areas
- app/api/chat/route.ts[8-41]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


View more (6)
4. ChatInterface uses any tool parsing 📘 Rule violation ⚙ Maintainability
Description
components/chat/chat-interface.tsx introduces any types for skillPlatform, messages, tool
invocation objects, and tool args without justification comments. This defeats strict typing in a
core UI flow and violates the compliance requirement.
Code

components/chat/chat-interface.tsx[R74-121]

+  // Parse conversation to extract skills and documents
+  let skillName = ''
+  let skillSlug = ''
+  let skillPlatform: any = 'all'
+  let skillMd = ''
+  const extraFiles: { path: string; content: string }[] = []
+  let isReadyToPackage = false
+
+  messages.forEach((message: any) => {
+    if (message.toolInvocations) {
+      message.toolInvocations.forEach((tool: any) => {
+        const { toolName, args } = tool
+        
+        if (toolName === 'generateSkillMd') {
+          const { name, slug, platform, content } = args as any
+          if (name) skillName = name
+          if (slug) skillSlug = slug
+          if (platform) skillPlatform = platform
+          if (content) skillMd = content
+        }
+        
+        if (toolName === 'generateScript') {
+          const { path, content } = args as any
+          if (path && content) {
+            const idx = extraFiles.findIndex(f => f.path === path)
+            if (idx >= 0) {
+              extraFiles[idx].content = content
+            } else {
+              extraFiles.push({ path, content })
+            }
+          }
+        }
+        
+        if (toolName === 'packageSkill') {
+          const { ready } = args as any
+          if (ready) {
+            isReadyToPackage = true
+          }
+        }
+      })
+    }
+  })
+
+  // Auto-save generated skill into local list when packaged successfully
+  useEffect(() => {
+    if (isReadyToPackage && skillName && skillMd) {
+      const saved = localStorage.getItem('ss_skills')
+      let list: any[] = []
Evidence
PR Compliance ID 2 requires strict TypeScript and forbids introducing any without documented
necessity. The new ChatInterface code uses multiple any annotations and args as any casts for
tool invocation parsing with no justification comment.

AGENTS.md: Enforce Strict TypeScript: Avoid 'any' Casts Unless Justified and Documented: AGENTS.md: Enforce Strict TypeScript: Avoid 'any' Casts Unless Justified and Documented: AGENTS.md: Enforce Strict TypeScript: Avoid 'any' Casts Unless Justified and Documented: AGENTS.md: Enforce Strict TypeScript: Avoid 'any' Casts Unless Justified and Documented
components/chat/chat-interface.tsx[74-121]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Tool invocation parsing in `ChatInterface` relies on `any` for message/tool/args/list types.
## Issue Context
The tool shapes are already described by Zod schemas in `lib/agent/tools.ts`. Use those schemas to derive types (e.g., `z.infer<...>`) and type the tool invocations/messages accordingly, removing `any` casts.
## Fix Focus Areas
- components/chat/chat-interface.tsx[74-151]
- lib/agent/tools.ts[3-50]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


5. tool.args cast to any ✓ Resolved 📘 Rule violation ⚙ Maintainability
Description
components/chat/chat-messages.tsx casts tool.args/tool.result to any and also defines
toolInvocations?: any[] without justification comments. This violates the strict TypeScript rule
and makes the UI rendering brittle.
Code

components/chat/chat-messages.tsx[R93-106]

+                      {toolName === 'generateScript' && (
+                        <span>
+                          {isCall 
+                            ? `Generating helper script: ${(tool.args as any).path}...` 
+                            : `Created script file: ${(tool.args as any).path}`}
+                        </span>
+                      )}
+                      {toolName === 'validateSkill' && (
+                        <span>
+                          {isCall 
+                            ? 'Running validation tests...' 
+                            : (tool.result as any)?.isValid 
+                              ? 'Skill validation passed cleanly' 
+                              : 'Skill validation completed with feedback'}
Evidence
PR Compliance ID 2 forbids any unless justified/documented. This file introduces
toolInvocations?: any[] and uses (tool.args as any) / (tool.result as any) with no explanatory
comment.

AGENTS.md: Enforce Strict TypeScript: Avoid 'any' Casts Unless Justified and Documented: AGENTS.md: Enforce Strict TypeScript: Avoid 'any' Casts Unless Justified and Documented: AGENTS.md: Enforce Strict TypeScript: Avoid 'any' Casts Unless Justified and Documented: AGENTS.md: Enforce Strict TypeScript: Avoid 'any' Casts Unless Justified and Documented
components/chat/chat-messages.tsx[1-6]
components/chat/chat-messages.tsx[93-106]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The chat message rendering relies on `any` for tool invocations and their args/results.
## Issue Context
Define a typed ToolInvocation union (based on the known tool names and their Zod-derived arg/result types) and apply it to `Message.toolInvocations`, eliminating `any` casts.
## Fix Focus Areas
- components/chat/chat-messages.tsx[1-6]
- components/chat/chat-messages.tsx[93-107]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


6. agentTools.execute uses args: any ✓ Resolved 📘 Rule violation ⚙ Maintainability
Description
lib/agent/tools.ts defines each tool execute handler as (args: any) => args without
justification comments. This violates the strict TypeScript compliance requirement and prevents
type-safe tool usage across the app.
Code

lib/agent/tools.ts[R4-21]

+  askQuestion: {
+    description: 'Ask the developer a specific clarifying question to gather more context about the skill requirements.',
+    parameters: z.object({
+      question: z.string().describe('The clarifying question to ask the developer.'),
+    }),
+    execute: async (args: any) => args,
+  },
+  
+  generateSkillMd: {
+    description: 'Generate the main SKILL.md file content based on the developer requirements.',
+    parameters: z.object({
+      name: z.string().describe('Name of the skill in clean title case (e.g. "Instagram Carousel Designer" or "Tailwind Refactoring Agent").'),
+      slug: z.string().describe('Kebab-case slug for the folder name (e.g. "carousel-instagram").'),
+      platform: z.enum(['claude', 'cursor', 'windsurf', 'gpt', 'all']).describe('AI assistant or editor this skill is primarily designed for.'),
+      content: z.string().describe('Full markdown content of the SKILL.md file, following standard skill formats (frontmatter with name and description, trigger examples, step-by-step instructions, and input/output examples).'),
+    }),
+    execute: async (args: any) => args,
+  },
Evidence
PR Compliance ID 2 forbids introducing any without documented necessity. The tool execute
handlers accept args: any multiple times with no justification comment.

AGENTS.md: Enforce Strict TypeScript: Avoid 'any' Casts Unless Justified and Documented: AGENTS.md: Enforce Strict TypeScript: Avoid 'any' Casts Unless Justified and Documented: AGENTS.md: Enforce Strict TypeScript: Avoid 'any' Casts Unless Justified and Documented: AGENTS.md: Enforce Strict TypeScript: Avoid 'any' Casts Unless Justified and Documented
lib/agent/tools.ts[4-21]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Tool `execute` handlers accept `args: any`.
## Issue Context
Each tool already defines a Zod `parameters` schema. Split schemas into named constants and use `z.infer<typeof Schema>` to strongly type `execute` args (and, if applicable, return types) without `any`.
## Fix Focus Areas
- lib/agent/tools.ts[3-49]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


7. Export route uses any 📘 Rule violation ⚙ Maintainability
Description
app/api/export/route.ts introduces both zipBuffer as any and catch (error: any) without any
justification comment. This violates the strict TypeScript compliance requirement and weakens type
safety for a core export API.
Code

app/api/export/route.ts[R23-32]

+    return new Response(new Blob([zipBuffer as any]), {
+      status: 200,
+      headers: {
+        'Content-Type': 'application/zip',
+        'Content-Disposition': `attachment; filename="${slug}.skill.zip"`,
+        'Cache-Control': 'no-store, max-age=0',
+      },
+    })
+  } catch (error: any) {
+    console.error('Error in API Export Route:', error)
Evidence
PR Compliance ID 2 forbids any unless unavoidable and documented. The export route uses as any
and an error: any catch parameter with no explanatory comment.

AGENTS.md: Enforce Strict TypeScript: Avoid 'any' Casts Unless Justified and Documented: AGENTS.md: Enforce Strict TypeScript: Avoid 'any' Casts Unless Justified and Documented: AGENTS.md: Enforce Strict TypeScript: Avoid 'any' Casts Unless Justified and Documented: AGENTS.md: Enforce Strict TypeScript: Avoid 'any' Casts Unless Justified and Documented
app/api/export/route.ts[23-32]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The export route uses `zipBuffer as any` and `catch (error: any)`.
## Issue Context
You can return the `Uint8Array` directly in the `Response` body (no `Blob` cast needed) and use `unknown` in the catch block with narrowing, preserving strict typing.
## Fix Focus Areas
- app/api/export/route.ts[16-36]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


8. Server key fallback abuse 🐞 Bug ⛨ Security
Description
/api/chat accepts an empty x-api-key and getModelInstance falls back to server environment API
keys, allowing unauthenticated callers to spend server-owned LLM credits. Unsupported/invalid
provider values also currently bubble into a thrown error path rather than a clean 4xx validation
response.
Code

lib/models/providers.ts[R7-23]

+export const getModelInstance = (provider: ModelProvider, apiKey: string, modelName?: string) => {
+  if (provider === 'gemini') {
+    const googleInstance = createGoogle({
+      apiKey: apiKey || process.env.GEMINI_API_KEY || '',
+    })
+    // Gemini 2.0 Flash is the default development model
+    return googleInstance(modelName || 'gemini-2.0-flash')
+  } else if (provider === 'claude') {
+    const anthropicInstance = createAnthropic({
+      apiKey: apiKey || process.env.ANTHROPIC_API_KEY || '',
+    })
+    return anthropicInstance(modelName || 'claude-3-5-sonnet-20241022')
+  } else if (provider === 'gpt') {
+    const openaiInstance = createOpenAI({
+      apiKey: apiKey || process.env.OPENAI_API_KEY || '',
+    })
+    return openaiInstance(modelName || 'gpt-4o-mini')
Evidence
The route reads x-api-key but does not require it, and provider factory code explicitly falls back
to server env keys when the header is empty, enabling server-key usage by any caller.

app/api/chat/route.ts[13-25]
lib/models/providers.ts[7-23]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`getModelInstance()` falls back to `process.env.*` keys when the request does not provide `x-api-key`, and `/api/chat` does not enforce that header. This makes the endpoint abusable to drain server/provider quotas.
### Issue Context
The UI stores keys in localStorage and forwards them via `x-api-key`, so server-side env fallback is not necessary for the intended design.
### Fix Focus Areas
- Validate and require `x-api-key` for all providers (return 400/401 when missing).
- Remove (or strictly gate) `process.env.*` API key fallback in `getModelInstance`.
- Validate `provider` to return 400 on unsupported values (avoid throwing into 500).
### Fix Focus Areas (code pointers)
- app/api/chat/route.ts[10-35]
- lib/models/providers.ts[7-25]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


9. Unsafe ZIP entry paths 🐞 Bug ⛨ Security
Description
/api/export passes caller-controlled files[].path directly into JSZip entry names without
sanitizing .. segments or absolute paths, creating archives that can perform Zip-Slip style
overwrites when extracted with a vulnerable/unhardened unzipper. The endpoint also does not validate
that files is an array of {path, content} strings, so malformed inputs can crash packaging
(500).
Code

lib/packager.ts[R33-37]

+  extraFiles.forEach((file) => {
+    // Normalize path separators to forward slashes for zip
+    const normalizedPath = file.path.replace(/\\/g, '/')
+    skillFolder.file(normalizedPath, file.content)
+  })
Evidence
The export route forwards files directly to the packager, and the packager uses file.path as the
ZIP entry name without removing .. or absolute path forms.

app/api/export/route.ts[6-18]
lib/packager.ts[32-37]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The export pipeline writes arbitrary `files[].path` into ZIP entries after only normalizing path separators. Paths like `../.ssh/config` or `/etc/passwd` (or Windows drive paths) can end up as unsafe archive entry names.
### Issue Context
- `app/api/export` accepts `files` from the request body.
- `lib/packager` writes those paths verbatim into the archive.
### Fix Focus Areas
- Validate request body shape (`skillName`, `skillMd`, and `files` array) before packaging.
- Reject absolute paths and any path containing `..` segments after normalization.
- Consider enforcing an allowlist of top-level directories (e.g., `scripts/`, `references/`, `assets/`, `templates/`).
- Optionally normalize to a safe prefix (e.g., always write under `generated/` inside the skill folder).
### Fix Focus Areas (code pointers)
- app/api/export/route.ts[6-22]
- lib/packager.ts[18-37]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

10. Supabase placeholder fallbacks 🐞 Bug ☼ Reliability
Description
Supabase client/server helpers silently fall back to hard-coded placeholder URL/key values when env
vars are missing, which hides configuration errors and can lead to confusing runtime behavior
(requests directed at an invalid host/key). This should fail fast or be explicitly mocked per
environment instead of silently defaulting.
Code

lib/supabase/server.ts[R4-8]

+export const createClient = async () => {
+  const cookieStore = await cookies()
+  const supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL || 'https://placeholder-url.supabase.co'
+  const supabaseAnonKey = process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY || 'placeholder-anon-key'
+
Evidence
Both Supabase helpers default to placeholder URL/key strings rather than requiring environment
configuration, which prevents early detection of misconfiguration.

lib/supabase/server.ts[4-8]
lib/supabase/client.ts[3-7]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`createClient()` for Supabase uses placeholder values when `NEXT_PUBLIC_SUPABASE_URL` / `NEXT_PUBLIC_SUPABASE_ANON_KEY` are missing. This masks misconfiguration and can cause non-obvious failures.
### Issue Context
Both browser and server Supabase clients use the same placeholder fallback behavior.
### Fix Focus Areas
- Replace placeholder fallbacks with explicit runtime checks and throw a clear error when env vars are missing.
- If local mock behavior is desired, gate it behind `NODE_ENV !== 'production'` and an explicit `SUPABASE_MOCK=true` flag.
### Fix Focus Areas (code pointers)
- lib/supabase/server.ts[4-8]
- lib/supabase/client.ts[3-7]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


11. Render-driven autosave rewrites ✓ Resolved 🐞 Bug ➹ Performance
Description
ChatInterface rebuilds extraFiles on every render and includes it in the autosave effect
dependency array, so once isReadyToPackage becomes true the effect can re-run on subsequent
renders and repeatedly rewrite ss_skills. This can cause unnecessary synchronous localStorage
writes and churn, especially with long chats or large generated content.
Code

components/chat/chat-interface.tsx[R74-150]

+  // Parse conversation to extract skills and documents
+  let skillName = ''
+  let skillSlug = ''
+  let skillPlatform: any = 'all'
+  let skillMd = ''
+  const extraFiles: { path: string; content: string }[] = []
+  let isReadyToPackage = false
+
+  messages.forEach((message: any) => {
+    if (message.toolInvocations) {
+      message.toolInvocations.forEach((tool: any) => {
+        const { toolName, args } = tool
+        
+        if (toolName === 'generateSkillMd') {
+          const { name, slug, platform, content } = args as any
+          if (name) skillName = name
+          if (slug) skillSlug = slug
+          if (platform) skillPlatform = platform
+          if (content) skillMd = content
+        }
+        
+        if (toolName === 'generateScript') {
+          const { path, content } = args as any
+          if (path && content) {
+            const idx = extraFiles.findIndex(f => f.path === path)
+            if (idx >= 0) {
+              extraFiles[idx].content = content
+            } else {
+              extraFiles.push({ path, content })
+            }
+          }
+        }
+        
+        if (toolName === 'packageSkill') {
+          const { ready } = args as any
+          if (ready) {
+            isReadyToPackage = true
+          }
+        }
+      })
+    }
+  })
+
+  // Auto-save generated skill into local list when packaged successfully
+  useEffect(() => {
+    if (isReadyToPackage && skillName && skillMd) {
+      const saved = localStorage.getItem('ss_skills')
+      let list: any[] = []
+      if (saved) {
+        try {
+          list = JSON.parse(saved)
+        } catch (e) {
+          console.error('Failed to parse saved skills index:', e)
+        }
+      }
+      
+      const newSlug = skillSlug || skillName.toLowerCase().trim().replace(/[^a-z0-9]+/g, '-')
+      const newSkill = {
+        id: newSlug,
+        name: skillName,
+        slug: newSlug,
+        platform: skillPlatform,
+        skillMd: skillMd,
+        files: extraFiles,
+        isComplete: true,
+        createdAt: new Date().toISOString()
+      }
+      
+      const idx = list.findIndex(s => s.slug === newSlug)
+      if (idx >= 0) {
+        list[idx] = newSkill
+      } else {
+        list.push(newSkill)
+      }
+      localStorage.setItem('ss_skills', JSON.stringify(list))
+    }
+  }, [isReadyToPackage, skillName, skillSlug, skillPlatform, skillMd, extraFiles])
Evidence
The code declares extraFiles as a new array each render and lists it in the useEffect dependency
array, so renders after packaging can retrigger the effect and rewrite localStorage.

components/chat/chat-interface.tsx[74-150]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The autosave effect depends on `extraFiles`, but `extraFiles` is a newly created array each render. That makes the effect eligible to rerun on every subsequent render while `isReadyToPackage` remains true.
### Issue Context
Parsed skill state (`skillName`, `skillMd`, `extraFiles`, etc.) is derived from `messages` inline on every render.
### Fix Focus Areas
- Derive parsed skill state via `useMemo(() => parse(messages), [messages])` so `extraFiles` has stable identity.
- Trigger autosave only on a meaningful transition (e.g., `isReadyToPackage` false -> true) using a `useRef` previous value, or by keying on a stable hash/signature.
### Fix Focus Areas (code pointers)
- components/chat/chat-interface.tsx[74-150]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Qodo Logo

Comment thread app/globals.css
Comment on lines +29 to +34
/* Custom grid background for signature cards */
.skill-card-grid {
background-image:
linear-gradient(rgba(99, 102, 241, 0.06) 1px, transparent 1px),
linear-gradient(90deg, rgba(99, 102, 241, 0.06) 1px, transparent 1px);
background-size: 24px 24px;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

1. skill-card-grid uses gradients 📘 Rule violation ⚙ Maintainability

The .skill-card-grid background is built with linear-gradient(...), which violates the
design-system rule forbidding any CSS gradient usage. This can cause repeated visual regressions
against the strict SkillStudio styling constraints.
Agent Prompt
## Issue description
`app/globals.css` uses `linear-gradient(...)` to render the signature card grid, but the design system forbids any CSS gradients.

## Issue Context
The grid effect can be implemented without CSS gradients (e.g., using an SVG background image or a data-URI) while preserving the required `#6366F1` @ 6% opacity and `24px 24px` sizing.

## Fix Focus Areas
- app/globals.css[29-35]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +102 to +106
<Button
variant="secondary"
onClick={handleClear}
className="flex items-center gap-2 text-rose-600 border-rose-200 hover:bg-rose-50 hover:text-rose-700"
>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

2. clear keys uses rose accent 📘 Rule violation ⚙ Maintainability

The Clear Keys button introduces rose colors (text-rose-600, border-rose-200,
hover:bg-rose-50), which violates the rule that #6366F1 is the single visual accent color. This
breaks the strict SkillStudio design system constraints.
Agent Prompt
## Issue description
A non-indigo accent color (`rose-*`) is used for the destructive `Clear Keys` button.

## Issue Context
The design system requires `#6366F1` as the single visual accent (with `#22C55E` reserved only for positive/ready indicators). Destructive actions should still be represented using approved neutrals/indigo styling patterns.

## Fix Focus Areas
- app/(app)/settings/page.tsx[98-109]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment thread app/api/chat/route.ts
Comment on lines +24 to +36
const model = getModelInstance(provider as ModelProvider, apiKey, modelName) as any

// Call streamText with automatic tool execution (up to 5 steps)
const result = streamText({
model,
system: SYSTEM_PROMPT,
messages,
tools: agentTools,
maxSteps: 5,
} as any)

return (result as any).toDataStreamResponse()
} catch (error: any) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

3. Chat route uses any casts 📘 Rule violation ⚙ Maintainability

app/api/chat/route.ts introduces multiple any casts and an error: any catch parameter without
any justification comment. This erases type safety and violates the strict TypeScript compliance
requirement.
Agent Prompt
## Issue description
The API route uses `as any` and `catch (error: any)` without documented necessity.

## Issue Context
Compliance requires avoiding `any` unless unavoidable and explicitly documented. This route can typically be typed by:
- Validating/parsing the JSON body (e.g., with Zod) into a concrete type
- Using `unknown` in catch and narrowing
- Avoiding `as any` around `streamText` options and the returned result

## Fix Focus Areas
- app/api/chat/route.ts[8-41]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +74 to +121
// Parse conversation to extract skills and documents
let skillName = ''
let skillSlug = ''
let skillPlatform: any = 'all'
let skillMd = ''
const extraFiles: { path: string; content: string }[] = []
let isReadyToPackage = false

messages.forEach((message: any) => {
if (message.toolInvocations) {
message.toolInvocations.forEach((tool: any) => {
const { toolName, args } = tool

if (toolName === 'generateSkillMd') {
const { name, slug, platform, content } = args as any
if (name) skillName = name
if (slug) skillSlug = slug
if (platform) skillPlatform = platform
if (content) skillMd = content
}

if (toolName === 'generateScript') {
const { path, content } = args as any
if (path && content) {
const idx = extraFiles.findIndex(f => f.path === path)
if (idx >= 0) {
extraFiles[idx].content = content
} else {
extraFiles.push({ path, content })
}
}
}

if (toolName === 'packageSkill') {
const { ready } = args as any
if (ready) {
isReadyToPackage = true
}
}
})
}
})

// Auto-save generated skill into local list when packaged successfully
useEffect(() => {
if (isReadyToPackage && skillName && skillMd) {
const saved = localStorage.getItem('ss_skills')
let list: any[] = []

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

4. Chatinterface uses any tool parsing 📘 Rule violation ⚙ Maintainability

components/chat/chat-interface.tsx introduces any types for skillPlatform, messages, tool
invocation objects, and tool args without justification comments. This defeats strict typing in a
core UI flow and violates the compliance requirement.
Agent Prompt
## Issue description
Tool invocation parsing in `ChatInterface` relies on `any` for message/tool/args/list types.

## Issue Context
The tool shapes are already described by Zod schemas in `lib/agent/tools.ts`. Use those schemas to derive types (e.g., `z.infer<...>`) and type the tool invocations/messages accordingly, removing `any` casts.

## Fix Focus Areas
- components/chat/chat-interface.tsx[74-151]
- lib/agent/tools.ts[3-50]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment thread components/chat/chat-messages.tsx
Comment thread app/api/export/route.ts
Comment on lines +23 to +32
return new Response(new Blob([zipBuffer as any]), {
status: 200,
headers: {
'Content-Type': 'application/zip',
'Content-Disposition': `attachment; filename="${slug}.skill.zip"`,
'Cache-Control': 'no-store, max-age=0',
},
})
} catch (error: any) {
console.error('Error in API Export Route:', error)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

7. Export route uses any 📘 Rule violation ⚙ Maintainability

app/api/export/route.ts introduces both zipBuffer as any and catch (error: any) without any
justification comment. This violates the strict TypeScript compliance requirement and weakens type
safety for a core export API.
Agent Prompt
## Issue description
The export route uses `zipBuffer as any` and `catch (error: any)`.

## Issue Context
You can return the `Uint8Array` directly in the `Response` body (no `Blob` cast needed) and use `unknown` in the catch block with narrowing, preserving strict typing.

## Fix Focus Areas
- app/api/export/route.ts[16-36]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment thread lib/models/providers.ts
Comment on lines +7 to +23
export const getModelInstance = (provider: ModelProvider, apiKey: string, modelName?: string) => {
if (provider === 'gemini') {
const googleInstance = createGoogle({
apiKey: apiKey || process.env.GEMINI_API_KEY || '',
})
// Gemini 2.0 Flash is the default development model
return googleInstance(modelName || 'gemini-2.0-flash')
} else if (provider === 'claude') {
const anthropicInstance = createAnthropic({
apiKey: apiKey || process.env.ANTHROPIC_API_KEY || '',
})
return anthropicInstance(modelName || 'claude-3-5-sonnet-20241022')
} else if (provider === 'gpt') {
const openaiInstance = createOpenAI({
apiKey: apiKey || process.env.OPENAI_API_KEY || '',
})
return openaiInstance(modelName || 'gpt-4o-mini')

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

8. Server key fallback abuse 🐞 Bug ⛨ Security

/api/chat accepts an empty x-api-key and getModelInstance falls back to server environment API
keys, allowing unauthenticated callers to spend server-owned LLM credits. Unsupported/invalid
provider values also currently bubble into a thrown error path rather than a clean 4xx validation
response.
Agent Prompt
### Issue description
`getModelInstance()` falls back to `process.env.*` keys when the request does not provide `x-api-key`, and `/api/chat` does not enforce that header. This makes the endpoint abusable to drain server/provider quotas.

### Issue Context
The UI stores keys in localStorage and forwards them via `x-api-key`, so server-side env fallback is not necessary for the intended design.

### Fix Focus Areas
- Validate and require `x-api-key` for all providers (return 400/401 when missing).
- Remove (or strictly gate) `process.env.*` API key fallback in `getModelInstance`.
- Validate `provider` to return 400 on unsupported values (avoid throwing into 500).

### Fix Focus Areas (code pointers)
- app/api/chat/route.ts[10-35]
- lib/models/providers.ts[7-25]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment thread lib/packager.ts
Comment on lines +33 to +37
extraFiles.forEach((file) => {
// Normalize path separators to forward slashes for zip
const normalizedPath = file.path.replace(/\\/g, '/')
skillFolder.file(normalizedPath, file.content)
})

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

9. Unsafe zip entry paths 🐞 Bug ⛨ Security

/api/export passes caller-controlled files[].path directly into JSZip entry names without
sanitizing .. segments or absolute paths, creating archives that can perform Zip-Slip style
overwrites when extracted with a vulnerable/unhardened unzipper. The endpoint also does not validate
that files is an array of {path, content} strings, so malformed inputs can crash packaging
(500).
Agent Prompt
### Issue description
The export pipeline writes arbitrary `files[].path` into ZIP entries after only normalizing path separators. Paths like `../.ssh/config` or `/etc/passwd` (or Windows drive paths) can end up as unsafe archive entry names.

### Issue Context
- `app/api/export` accepts `files` from the request body.
- `lib/packager` writes those paths verbatim into the archive.

### Fix Focus Areas
- Validate request body shape (`skillName`, `skillMd`, and `files` array) before packaging.
- Reject absolute paths and any path containing `..` segments after normalization.
- Consider enforcing an allowlist of top-level directories (e.g., `scripts/`, `references/`, `assets/`, `templates/`).
- Optionally normalize to a safe prefix (e.g., always write under `generated/` inside the skill folder).

### Fix Focus Areas (code pointers)
- app/api/export/route.ts[6-22]
- lib/packager.ts[18-37]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment thread lib/supabase/server.ts
Comment on lines +4 to +8
export const createClient = async () => {
const cookieStore = await cookies()
const supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL || 'https://placeholder-url.supabase.co'
const supabaseAnonKey = process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY || 'placeholder-anon-key'

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remediation recommended

10. Supabase placeholder fallbacks 🐞 Bug ☼ Reliability

Supabase client/server helpers silently fall back to hard-coded placeholder URL/key values when env
vars are missing, which hides configuration errors and can lead to confusing runtime behavior
(requests directed at an invalid host/key). This should fail fast or be explicitly mocked per
environment instead of silently defaulting.
Agent Prompt
### Issue description
`createClient()` for Supabase uses placeholder values when `NEXT_PUBLIC_SUPABASE_URL` / `NEXT_PUBLIC_SUPABASE_ANON_KEY` are missing. This masks misconfiguration and can cause non-obvious failures.

### Issue Context
Both browser and server Supabase clients use the same placeholder fallback behavior.

### Fix Focus Areas
- Replace placeholder fallbacks with explicit runtime checks and throw a clear error when env vars are missing.
- If local mock behavior is desired, gate it behind `NODE_ENV !== 'production'` and an explicit `SUPABASE_MOCK=true` flag.

### Fix Focus Areas (code pointers)
- lib/supabase/server.ts[4-8]
- lib/supabase/client.ts[3-7]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment thread components/chat/chat-interface.tsx
@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Implement SkillStudio app with BYOK local key storage and AI SDK v5 streaming

✨ Enhancement 📝 Documentation ⚙️ Configuration changes 🕐 40+ Minutes

Grey Divider

AI Description

• Adds SkillStudio UI: landing, dashboard, generation chat, and settings screens.
• Implements AI SDK v5 streaming chat with tool-calling skill generation and ZIP export.
• Ensures BYOK safety: API keys stay in localStorage and are sent only via headers.
Diagram

sequenceDiagram
  actor User
  participant UI as "Chat UI"
  participant LS as "localStorage"
  participant Chat as "/api/chat"
  participant LLM as "AI Provider"
  participant Export as "/api/export"

  User->>UI: Enter requirements
  UI->>LS: Read ss_api_key_{provider}
  UI->>Chat: POST messages + x-api-key
  Chat->>LLM: streamText(system+tools)
  LLM-->>UI: Stream text + tool calls
  UI->>LS: Persist ss_skills index
  User->>UI: Download package
  UI->>Export: POST skillName/skillMd/files
  Export-->>UI: ZIP binary response
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Use server-managed auth/session for provider access
  • ➕ Avoids storing long-lived secrets in browser localStorage
  • ➕ Enables centralized usage controls (rate limits, quotas, auditing)
  • ➖ Requires operating/collecting API keys or implementing OAuth/provider auth
  • ➖ Higher infra and compliance burden; deviates from BYOK/no-server-storage goal
2. Session-only key storage (sessionStorage + optional in-memory)
  • ➕ Reduces persistence window versus localStorage
  • ➕ Limits key exposure if the device is shared
  • ➖ Worse UX (keys lost on tab/browser close)
  • ➖ Does not prevent XSS-based access; still a client-side secret
3. Encrypt keys at rest in localStorage (WebCrypto)
  • ➕ Mitigates casual local inspection of keys on disk
  • ➕ Can be paired with a user passphrase for better protection
  • ➖ Does not protect against XSS/runtime access (keys must be decrypted to use)
  • ➖ Adds complexity and recovery/UX issues (forgotten passphrases)

Recommendation: Given the stated BYOK constraint (“keys never touch our database”), the PR’s approach (localStorage + header forwarding to a server-side proxy route) is the most practical. If threat model includes shared devices, consider sessionStorage/in-memory as an optional mode; if threat model includes XSS, the only robust mitigation is preventing XSS (CSP, rigorous sanitization) rather than encrypting localStorage.

Files changed (160) +21974 / -27

Enhancement (22) +1628 / -9
page.tsxAdd dashboard listing locally stored skills +147/-0

Add dashboard listing locally stored skills

• Implements a client dashboard that loads skills from localStorage, provides regenerate navigation, and triggers server ZIP exports for download.

app/(app)/dashboard/page.tsx

page.tsxAdd generation page with Suspense-wrapped chat workspace +18/-0

Add generation page with Suspense-wrapped chat workspace

• Adds a generate route that renders the chat interface and shows a loading fallback during initialization.

app/(app)/generate/page.tsx

layout.tsxAdd authenticated/app layout with persistent sidebar +16/-0

Add authenticated/app layout with persistent sidebar

• Introduces an app shell layout that hosts the sidebar and main content region for app routes.

app/(app)/layout.tsx

page.tsxAdd settings page for per-provider API keys +114/-0

Add settings page for per-provider API keys

• Implements a settings UI for saving/clearing Gemini/Claude/OpenAI keys in localStorage with user-facing security messaging.

app/(app)/settings/page.tsx

page.tsxAdd marketing landing page +90/-0

Add marketing landing page

• Adds a landing page describing the product flow and linking to generation and GitHub.

app/(marketing)/page.tsx

route.tsAdd AI SDK v5 streaming chat route with tool execution +43/-0

Add AI SDK v5 streaming chat route with tool execution

• Implements a streaming POST endpoint that selects a provider/model, applies a system prompt, enables tool-calling, and returns a data stream response.

app/api/chat/route.ts

route.tsAdd ZIP export route for generated skills +38/-0

Add ZIP export route for generated skills

• Implements a POST endpoint that packages SKILL.md plus extra files into a downloadable .zip with no-store caching.

app/api/export/route.ts

layout.tsxUpdate app fonts and metadata for SkillStudio branding +16/-9

Update app fonts and metadata for SkillStudio branding

• Replaces default fonts with Space Grotesk/Inter/JetBrains Mono and updates app metadata/title/description and base body styling.

app/layout.tsx

chat-input.tsxAdd chat input with Enter-to-submit behavior +48/-0

Add chat input with Enter-to-submit behavior

• Adds a textarea input component with keyboard handling and a submit button wired for loading/disabled states.

components/chat/chat-input.tsx

chat-interface.tsxAdd chat workspace with provider selection, tool parsing, and preview +251/-0

Add chat workspace with provider selection, tool parsing, and preview

• Implements the main generation experience: model selection, local key editing, AI SDK 'useChat' streaming, tool invocation parsing into skill artifacts, local persistence, and download trigger.

components/chat/chat-interface.tsx

chat-messages.tsxAdd chat transcript renderer with tool-call status chips +124/-0

Add chat transcript renderer with tool-call status chips

• Renders user/assistant messages and displays tool invocation progress/completion indicators for the generation flow.

components/chat/chat-messages.tsx

model-selector.tsxAdd model provider selector UI +77/-0

Add model provider selector UI

• Introduces a button-based selector for Gemini/Claude/GPT providers with styling and icons.

components/chat/model-selector.tsx

skill-preview.tsxAdd skill preview panel with tabs and installation instructions +216/-0

Add skill preview panel with tabs and installation instructions

• Implements a preview panel for generated SKILL.md and files, copy-to-clipboard, install instructions per platform, and download gating until ready.

components/chat/skill-preview.tsx

sidebar.tsxAdd responsive sidebar navigation +129/-0

Add responsive sidebar navigation

• Implements mobile drawer + desktop sidebar navigation for dashboard/generate/settings routes.

components/dashboard/sidebar.tsx

skill-card.tsxAdd skill card UI with download/regenerate actions +84/-0

Add skill card UI with download/regenerate actions

• Adds a skill card component showing platform, files, readiness, and action buttons for export and regeneration.

components/dashboard/skill-card.tsx

skill-grid.tsxAdd skill grid layout +22/-0

Add skill grid layout

• Adds a grid component for rendering a list of skill cards with callbacks.

components/dashboard/skill-grid.tsx

button.tsxAdd reusable Button component with variants +26/-0

Add reusable Button component with variants

• Introduces a shared button component with variant styling and tailwind-merge class composition.

components/ui/button.tsx

logo.tsxAdd SkillStudio logo components +24/-0

Add SkillStudio logo components

• Adds a logo mark and linked brand wordmark used across marketing and app layouts.

components/ui/logo.tsx

system-prompt.tsAdd system prompt defining SkillStudio agent flow +17/-0

Add system prompt defining SkillStudio agent flow

• Defines the agent’s conversation/generation workflow and tool usage contract for SKILL.md creation and packaging readiness.

lib/agent/system-prompt.ts

tools.tsDefine Zod-typed tool schema for agent tool-calling +50/-0

Define Zod-typed tool schema for agent tool-calling

• Adds tool definitions (askQuestion, generateSkillMd, generateScript, validateSkill, packageSkill) used by AI SDK for structured outputs.

lib/agent/tools.ts

providers.tsAdd provider factory for Gemini/Claude/OpenAI +26/-0

Add provider factory for Gemini/Claude/OpenAI

• Implements provider selection and model instantiation using AI SDK provider factories, supporting header-provided keys or env fallbacks.

lib/models/providers.ts

packager.tsAdd JSZip-based skill packaging helpers +52/-0

Add JSZip-based skill packaging helpers

• Adds utilities to build a deterministic skill folder name, write SKILL.md and extra files, and produce a Uint8Array ZIP buffer.

lib/packager.ts

Documentation (133) +20229 / -0
SKILL.mdAdd Accessibility skill reference (WCAG 2.2-focused) +440/-0

Add Accessibility skill reference (WCAG 2.2-focused)

• Introduces a comprehensive accessibility skill document with WCAG principles, checklists, and guidance for audits and remediation.

.agents/skills/accessibility/SKILL.md

A11Y-PATTERNS.mdAdd reusable accessibility implementation patterns +233/-0

Add reusable accessibility implementation patterns

• Adds copy-paste UI patterns (e.g., focus trap, skip links, ARIA tabs) for common accessibility requirements.

.agents/skills/accessibility/references/A11Y-PATTERNS.md

WCAG.mdAdd WCAG 2.2 quick reference guide +191/-0

Add WCAG 2.2 quick reference guide

• Provides a condensed WCAG 2.2 reference, including levels, key criteria, and testing/tooling notes.

.agents/skills/accessibility/references/WCAG.md

SKILL.mdAdd Bun skill reference documentation +231/-0

Add Bun skill reference documentation

• Documents Bun overview, core commands, workflows, pitfalls, and verification checklist for JS/TS projects.

.agents/skills/bun/SKILL.md

LICENSE.txtAdd frontend-design skill license text +177/-0

Add frontend-design skill license text

• Adds the license file associated with the frontend-design skill content.

.agents/skills/frontend-design/LICENSE.txt

SKILL.mdAdd frontend-design skill documentation +42/-0

Add frontend-design skill documentation

• Introduces a short skill doc for frontend design guidance and usage context.

.agents/skills/frontend-design/SKILL.md

SKILL.mdAdd SEO skill reference documentation +513/-0

Add SEO skill reference documentation

• Adds an extensive SEO skill reference covering best practices, checks, and implementation guidance.

.agents/skills/seo/SKILL.md

SKILL.mdAdd Tailwind CSS patterns skill documentation +152/-0

Add Tailwind CSS patterns skill documentation

• Introduces Tailwind patterns skill doc and entry points to detailed references.

.agents/skills/tailwind-css-patterns/SKILL.md

accessibility.mdAdd Tailwind accessibility patterns reference +167/-0

Add Tailwind accessibility patterns reference

• Adds Tailwind-centric accessibility implementation notes and patterns.

.agents/skills/tailwind-css-patterns/references/accessibility.md

animations.mdAdd Tailwind animation patterns reference +141/-0

Add Tailwind animation patterns reference

• Adds animation and motion guidance/patterns for Tailwind-based UIs.

.agents/skills/tailwind-css-patterns/references/animations.md

component-patterns.mdAdd Tailwind component patterns reference +169/-0

Add Tailwind component patterns reference

• Documents common component composition patterns and conventions for Tailwind projects.

.agents/skills/tailwind-css-patterns/references/component-patterns.md

configuration.mdAdd Tailwind configuration reference +198/-0

Add Tailwind configuration reference

• Provides Tailwind configuration guidance, including theming and setup conventions.

.agents/skills/tailwind-css-patterns/references/configuration.md

layout-patterns.mdAdd Tailwind layout patterns reference +222/-0

Add Tailwind layout patterns reference

• Documents layout building blocks and responsive layout patterns using Tailwind.

.agents/skills/tailwind-css-patterns/references/layout-patterns.md

performance.mdAdd Tailwind performance reference +119/-0

Add Tailwind performance reference

• Adds guidance for keeping Tailwind output and runtime performance efficient.

.agents/skills/tailwind-css-patterns/references/performance.md

reference.mdAdd Tailwind master reference +508/-0

Add Tailwind master reference

• Adds a broad Tailwind reference guide consolidating utilities and usage patterns.

.agents/skills/tailwind-css-patterns/references/reference.md

responsive-design.mdAdd Tailwind responsive design reference +159/-0

Add Tailwind responsive design reference

• Documents responsive design practices and Tailwind breakpoint usage patterns.

.agents/skills/tailwind-css-patterns/references/responsive-design.md

SKILL.mdAdd TypeScript advanced types skill documentation +717/-0

Add TypeScript advanced types skill documentation

• Adds a comprehensive reference for advanced TypeScript typing patterns and best practices.

.agents/skills/typescript-advanced-types/SKILL.md

AGENTS.mdAdd Zod skill agent guidance +97/-0

Add Zod skill agent guidance

• Introduces agent-facing instructions for applying the Zod skill references consistently.

.agents/skills/zod/AGENTS.md

README.mdAdd Zod skill README +79/-0

Add Zod skill README

• Adds overview documentation for the Zod skill package and how to use the references.

.agents/skills/zod/README.md

SKILL.mdAdd Zod best practices skill +127/-0

Add Zod best practices skill

• Introduces a Zod best practices skill with categorized rules and application guidance.

.agents/skills/zod/SKILL.md

_template.mdAdd Zod template asset +30/-0

Add Zod template asset

• Adds a template markdown asset for structuring Zod-related reference content.

.agents/skills/zod/assets/templates/_template.md

metadata.jsonAdd Zod skill metadata +69/-0

Add Zod skill metadata

• Adds metadata describing the Zod skill package structure and contents.

.agents/skills/zod/metadata.json

_sections.mdAdd Zod references section index +46/-0

Add Zod references section index

• Adds a section index file organizing Zod reference topics.

.agents/skills/zod/references/_sections.md

compose-intersection.mdAdd Zod composition: intersection reference +144/-0

Add Zod composition: intersection reference

• Documents best practices for composing schemas via intersection.

.agents/skills/zod/references/compose-intersection.md

compose-lazy-recursive.mdAdd Zod composition: lazy/recursive reference +143/-0

Add Zod composition: lazy/recursive reference

• Documents patterns for recursive schemas using lazy evaluation.

.agents/skills/zod/references/compose-lazy-recursive.md

compose-pipe.mdAdd Zod composition: pipe reference +113/-0

Add Zod composition: pipe reference

• Documents schema composition using pipe and related patterns.

.agents/skills/zod/references/compose-pipe.md

compose-preprocess.mdAdd Zod composition: preprocess reference +142/-0

Add Zod composition: preprocess reference

• Documents preprocess usage for coercion and input normalization.

.agents/skills/zod/references/compose-preprocess.md

compose-shared-schemas.mdAdd Zod composition: shared schemas reference +137/-0

Add Zod composition: shared schemas reference

• Documents shared schema reuse patterns and composition guidelines.

.agents/skills/zod/references/compose-shared-schemas.md

error-avoid-throwing-in-refine.mdAdd Zod error handling: avoid throwing in refine +127/-0

Add Zod error handling: avoid throwing in refine

• Documents safer error-handling patterns in refine/superRefine flows.

.agents/skills/zod/references/error-avoid-throwing-in-refine.md

error-custom-messages.mdAdd Zod error handling: custom messages +118/-0

Add Zod error handling: custom messages

• Documents strategies for consistent, user-facing error messages.

.agents/skills/zod/references/error-custom-messages.md

error-i18n.mdAdd Zod error handling: i18n patterns +145/-0

Add Zod error handling: i18n patterns

• Documents internationalization approaches for validation errors.

.agents/skills/zod/references/error-i18n.md

error-path-for-nested.mdAdd Zod error handling: nested paths +130/-0

Add Zod error handling: nested paths

• Documents how to attach errors to nested paths for better UX.

.agents/skills/zod/references/error-path-for-nested.md

error-use-flatten.mdAdd Zod error handling: flatten usage +131/-0

Add Zod error handling: flatten usage

• Documents flattening error structures for UI display and reporting.

.agents/skills/zod/references/error-use-flatten.md

object-discriminated-unions.mdAdd Zod objects: discriminated unions +138/-0

Add Zod objects: discriminated unions

• Documents patterns for discriminated unions and safe narrowing.

.agents/skills/zod/references/object-discriminated-unions.md

object-extend-for-composition.mdAdd Zod objects: extend for composition +147/-0

Add Zod objects: extend for composition

• Documents composing object schemas via extend and reuse.

.agents/skills/zod/references/object-extend-for-composition.md

object-optional-vs-nullable.mdAdd Zod objects: optional vs nullable +117/-0

Add Zod objects: optional vs nullable

• Documents semantic differences and when to use optional vs nullable.

.agents/skills/zod/references/object-optional-vs-nullable.md

object-partial-for-updates.mdAdd Zod objects: partial updates reference +123/-0

Add Zod objects: partial updates reference

• Documents using partial and related patterns for update payloads.

.agents/skills/zod/references/object-partial-for-updates.md

object-pick-omit.mdAdd Zod objects: pick/omit reference +146/-0

Add Zod objects: pick/omit reference

• Documents deriving schemas using pick/omit for controlled exposure.

.agents/skills/zod/references/object-pick-omit.md

object-strict-vs-strip.mdAdd Zod objects: strict vs strip reference +109/-0

Add Zod objects: strict vs strip reference

• Documents handling unknown keys and the tradeoffs of strict vs strip.

.agents/skills/zod/references/object-strict-vs-strip.md

parse-async-for-async-refinements.mdAdd Zod parsing: async parse for async refinements +118/-0

Add Zod parsing: async parse for async refinements

• Documents when to use async parsing to support async refinements.

.agents/skills/zod/references/parse-async-for-async-refinements.md

parse-avoid-double-validation.mdAdd Zod parsing: avoid double validation +129/-0

Add Zod parsing: avoid double validation

• Documents patterns to prevent redundant validation work.

.agents/skills/zod/references/parse-avoid-double-validation.md

parse-handle-all-issues.mdAdd Zod parsing: handle all issues +125/-0

Add Zod parsing: handle all issues

• Documents aggregating and handling all issues for robust feedback.

.agents/skills/zod/references/parse-handle-all-issues.md

parse-never-trust-json.mdAdd Zod parsing: never trust JSON reference +113/-0

Add Zod parsing: never trust JSON reference

• Documents safe parsing assumptions and input validation guidelines.

.agents/skills/zod/references/parse-never-trust-json.md

parse-use-safeparse.mdAdd Zod parsing: safeParse usage +102/-0

Add Zod parsing: safeParse usage

• Documents safeParse patterns and error-first control flow.

.agents/skills/zod/references/parse-use-safeparse.md

parse-validate-early.mdAdd Zod parsing: validate early +120/-0

Add Zod parsing: validate early

• Documents validating inputs early to reduce downstream complexity.

.agents/skills/zod/references/parse-validate-early.md

perf-arrays.mdAdd Zod performance: arrays reference +153/-0

Add Zod performance: arrays reference

• Documents performance considerations for validating arrays.

.agents/skills/zod/references/perf-arrays.md

perf-avoid-dynamic-creation.mdAdd Zod performance: avoid dynamic schema creation +139/-0

Add Zod performance: avoid dynamic schema creation

• Documents avoiding per-call schema instantiation and related overhead.

.agents/skills/zod/references/perf-avoid-dynamic-creation.md

perf-cache-schemas.mdAdd Zod performance: cache schemas +138/-0

Add Zod performance: cache schemas

• Documents caching and reuse strategies for schema objects.

.agents/skills/zod/references/perf-cache-schemas.md

perf-lazy-loading.mdAdd Zod performance: lazy loading reference +135/-0

Add Zod performance: lazy loading reference

• Documents lazy-loading strategies for reducing bundle and runtime costs.

.agents/skills/zod/references/perf-lazy-loading.md

perf-zod-mini.mdAdd Zod performance: zod-mini guidance +117/-0

Add Zod performance: zod-mini guidance

• Documents when to consider zod-mini and bundle-size tradeoffs.

.agents/skills/zod/references/perf-zod-mini.md

refine-add-path.mdAdd Zod refine: add path reference +141/-0

Add Zod refine: add path reference

• Documents attaching errors to specific paths in refinement steps.

.agents/skills/zod/references/refine-add-path.md

refine-catch.mdAdd Zod refine: catch reference +143/-0

Add Zod refine: catch reference

• Documents safe error handling and catch usage around refinements.

.agents/skills/zod/references/refine-catch.md

refine-defaults.mdAdd Zod refine: defaults reference +131/-0

Add Zod refine: defaults reference

• Documents applying defaults consistently alongside refinements.

.agents/skills/zod/references/refine-defaults.md

refine-transform-coerce.mdAdd Zod refine: transform/coerce guidance +105/-0

Add Zod refine: transform/coerce guidance

• Documents how to combine transforms and coercion safely.

.agents/skills/zod/references/refine-transform-coerce.md

refine-vs-superrefine.mdAdd Zod refine vs superRefine reference +152/-0

Add Zod refine vs superRefine reference

• Documents when to use refine vs superRefine and their capabilities.

.agents/skills/zod/references/refine-vs-superrefine.md

schema-avoid-optional-abuse.mdAdd Zod schema: avoid optional abuse reference +93/-0

Add Zod schema: avoid optional abuse reference

• Documents keeping schemas strict and avoiding overuse of optional.

.agents/skills/zod/references/schema-avoid-optional-abuse.md

schema-coercion-for-form-data.mdAdd Zod schema: coercion for form data +88/-0

Add Zod schema: coercion for form data

• Documents coercion patterns for HTML form inputs and query params.

.agents/skills/zod/references/schema-coercion-for-form-data.md

schema-string-validations.mdAdd Zod schema: string validations reference +90/-0

Add Zod schema: string validations reference

• Documents robust string validation rules and reusable patterns.

.agents/skills/zod/references/schema-string-validations.md

schema-use-enums.mdAdd Zod schema: use enums reference +107/-0

Add Zod schema: use enums reference

• Documents enum usage patterns for constrained values.

.agents/skills/zod/references/schema-use-enums.md

schema-use-primitives-correctly.mdAdd Zod schema: primitives correctness reference +61/-0

Add Zod schema: primitives correctness reference

• Documents correct usage of primitive schema types and pitfalls.

.agents/skills/zod/references/schema-use-primitives-correctly.md

schema-use-unknown-not-any.mdAdd Zod schema: unknown over any reference +88/-0

Add Zod schema: unknown over any reference

• Documents preferring unknown and narrowing instead of any.

.agents/skills/zod/references/schema-use-unknown-not-any.md

type-branded-types.mdAdd Zod typing: branded types reference +102/-0

Add Zod typing: branded types reference

• Documents branded types patterns for stronger type safety.

.agents/skills/zod/references/type-branded-types.md

type-enable-strict-mode.mdAdd Zod typing: strict mode guidance +130/-0

Add Zod typing: strict mode guidance

• Documents TypeScript strict-mode considerations when using Zod.

.agents/skills/zod/references/type-enable-strict-mode.md

type-export-schemas-and-types.mdAdd Zod typing: export schemas/types reference +116/-0

Add Zod typing: export schemas/types reference

• Documents conventions for exporting schemas and inferred types.

.agents/skills/zod/references/type-export-schemas-and-types.md

type-input-vs-output.mdAdd Zod typing: input vs output reference +116/-0

Add Zod typing: input vs output reference

• Documents differences between input/output types and transforms.

.agents/skills/zod/references/type-input-vs-output.md

type-use-z-infer.mdAdd Zod typing: z.infer reference +110/-0

Add Zod typing: z.infer reference

• Documents consistent type inference using z.infer patterns.

.agents/skills/zod/references/type-use-z-infer.md

SKILL.mdMirror Accessibility skill into .claude directory +440/-0

Mirror Accessibility skill into .claude directory

• Adds the same accessibility skill reference content for Claude rule consumption.

.claude/skills/accessibility/SKILL.md

A11Y-PATTERNS.mdMirror accessibility patterns into .claude directory +233/-0

Mirror accessibility patterns into .claude directory

• Adds accessibility code patterns for Claude skill usage.

.claude/skills/accessibility/references/A11Y-PATTERNS.md

WCAG.mdMirror WCAG reference into .claude directory +191/-0

Mirror WCAG reference into .claude directory

• Adds WCAG quick reference for Claude skill usage.

.claude/skills/accessibility/references/WCAG.md

SKILL.mdMirror Bun skill into .claude directory +231/-0

Mirror Bun skill into .claude directory

• Adds Bun reference documentation for Claude skill usage.

.claude/skills/bun/SKILL.md

LICENSE.txtMirror frontend-design license into .claude directory +177/-0

Mirror frontend-design license into .claude directory

• Adds the license file for Claude skill bundle parity.

.claude/skills/frontend-design/LICENSE.txt

SKILL.mdMirror frontend-design skill into .claude directory +42/-0

Mirror frontend-design skill into .claude directory

• Adds frontend design skill documentation for Claude rule consumption.

.claude/skills/frontend-design/SKILL.md

SKILL.mdMirror SEO skill into .claude directory +513/-0

Mirror SEO skill into .claude directory

• Adds SEO reference documentation for Claude skill usage.

.claude/skills/seo/SKILL.md

SKILL.mdMirror Tailwind patterns skill into .claude directory +152/-0

Mirror Tailwind patterns skill into .claude directory

• Adds Tailwind patterns documentation for Claude skill usage.

.claude/skills/tailwind-css-patterns/SKILL.md

accessibility.mdMirror Tailwind accessibility reference into .claude +167/-0

Mirror Tailwind accessibility reference into .claude

• Adds Tailwind accessibility reference for Claude usage.

.claude/skills/tailwind-css-patterns/references/accessibility.md

animations.mdMirror Tailwind animations reference into .claude +141/-0

Mirror Tailwind animations reference into .claude

• Adds Tailwind animations reference for Claude usage.

.claude/skills/tailwind-css-patterns/references/animations.md

component-patterns.mdMirror Tailwind component patterns reference into .claude +169/-0

Mirror Tailwind component patterns reference into .claude

• Adds Tailwind component patterns reference for Claude usage.

.claude/skills/tailwind-css-patterns/references/component-patterns.md

configuration.mdMirror Tailwind configuration reference into .claude +198/-0

Mirror Tailwind configuration reference into .claude

• Adds Tailwind configuration reference for Claude usage.

.claude/skills/tailwind-css-patterns/references/configuration.md

layout-patterns.mdMirror Tailwind layout patterns reference into .claude +222/-0

Mirror Tailwind layout patterns reference into .claude

• Adds Tailwind layout patterns reference for Claude usage.

.claude/skills/tailwind-css-patterns/references/layout-patterns.md

performance.mdMirror Tailwind performance reference into .claude +119/-0

Mirror Tailwind performance reference into .claude

• Adds Tailwind performance reference for Claude usage.

.claude/skills/tailwind-css-patterns/references/performance.md

reference.mdMirror Tailwind master reference into .claude +508/-0

Mirror Tailwind master reference into .claude

• Adds Tailwind master reference for Claude usage.

.claude/skills/tailwind-css-patterns/references/reference.md

responsive-design.mdMirror Tailwind responsive reference into .claude +159/-0

Mirror Tailwind responsive reference into .claude

• Adds Tailwind responsive design reference for Claude usage.

.claude/skills/tailwind-css-patterns/references/responsive-design.md

SKILL.mdMirror TypeScript advanced types skill into .claude +717/-0

Mirror TypeScript advanced types skill into .claude

• Adds advanced TypeScript typing documentation for Claude usage.

.claude/skills/typescript-advanced-types/SKILL.md

AGENTS.mdMirror Zod AGENTS into .claude +97/-0

Mirror Zod AGENTS into .claude

• Adds Zod agent usage guidance for Claude directory.

.claude/skills/zod/AGENTS.md

README.mdMirror Zod README into .claude +79/-0

Mirror Zod README into .claude

• Adds Zod skill overview for Claude directory.

.claude/skills/zod/README.md

SKILL.mdMirror Zod SKILL into .claude +127/-0

Mirror Zod SKILL into .claude

• Adds Zod best practices skill for Claude directory.

.claude/skills/zod/SKILL.md

_template.mdMirror Zod template asset into .claude +30/-0

Mirror Zod template asset into .claude

• Adds template markdown asset for Claude directory parity.

.claude/skills/zod/assets/templates/_template.md

metadata.jsonMirror Zod metadata into .claude +69/-0

Mirror Zod metadata into .claude

• Adds metadata file describing Zod skill contents for Claude directory.

.claude/skills/zod/metadata.json

_sections.mdMirror Zod sections index into .claude +46/-0

Mirror Zod sections index into .claude

• Adds Zod topic index for Claude directory.

.claude/skills/zod/references/_sections.md

compose-intersection.mdMirror Zod compose-intersection reference into .claude +144/-0

Mirror Zod compose-intersection reference into .claude

• Adds Zod intersection composition guidance for Claude directory.

.claude/skills/zod/references/compose-intersection.md

compose-lazy-recursive.mdMirror Zod compose-lazy-recursive reference into .claude +143/-0

Mirror Zod compose-lazy-recursive reference into .claude

• Adds Zod lazy/recursive composition guidance for Claude directory.

.claude/skills/zod/references/compose-lazy-recursive.md

compose-pipe.mdMirror Zod compose-pipe reference into .claude +113/-0

Mirror Zod compose-pipe reference into .claude

• Adds Zod pipe composition guidance for Claude directory.

.claude/skills/zod/references/compose-pipe.md

compose-preprocess.mdMirror Zod compose-preprocess reference into .claude +142/-0

Mirror Zod compose-preprocess reference into .claude

• Adds Zod preprocess guidance for Claude directory.

.claude/skills/zod/references/compose-preprocess.md

compose-shared-schemas.mdMirror Zod compose-shared-schemas reference into .claude +137/-0

Mirror Zod compose-shared-schemas reference into .claude

• Adds shared schema composition guidance for Claude directory.

.claude/skills/zod/references/compose-shared-schemas.md

error-avoid-throwing-in-refine.mdMirror Zod error-avoid-throwing-in-refine into .claude +127/-0

Mirror Zod error-avoid-throwing-in-refine into .claude

• Adds refine error-handling guidance for Claude directory.

.claude/skills/zod/references/error-avoid-throwing-in-refine.md

error-custom-messages.mdMirror Zod error-custom-messages into .claude +118/-0

Mirror Zod error-custom-messages into .claude

• Adds custom message guidance for Claude directory.

.claude/skills/zod/references/error-custom-messages.md

error-i18n.mdMirror Zod error-i18n into .claude +145/-0

Mirror Zod error-i18n into .claude

• Adds i18n error patterns for Claude directory.

.claude/skills/zod/references/error-i18n.md

error-path-for-nested.mdMirror Zod error-path-for-nested into .claude +130/-0

Mirror Zod error-path-for-nested into .claude

• Adds nested error path guidance for Claude directory.

.claude/skills/zod/references/error-path-for-nested.md

error-use-flatten.mdMirror Zod error-use-flatten into .claude +131/-0

Mirror Zod error-use-flatten into .claude

• Adds flatten error guidance for Claude directory.

.claude/skills/zod/references/error-use-flatten.md

object-discriminated-unions.mdMirror Zod object-discriminated-unions into .claude +138/-0

Mirror Zod object-discriminated-unions into .claude

• Adds discriminated union guidance for Claude directory.

.claude/skills/zod/references/object-discriminated-unions.md

object-extend-for-composition.mdMirror Zod object-extend-for-composition into .claude +147/-0

Mirror Zod object-extend-for-composition into .claude

• Adds object extend composition guidance for Claude directory.

.claude/skills/zod/references/object-extend-for-composition.md

object-optional-vs-nullable.mdMirror Zod object-optional-vs-nullable into .claude +117/-0

Mirror Zod object-optional-vs-nullable into .claude

• Adds optional vs nullable guidance for Claude directory.

.claude/skills/zod/references/object-optional-vs-nullable.md

object-partial-for-updates.mdMirror Zod object-partial-for-updates into .claude +123/-0

Mirror Zod object-partial-for-updates into .claude

• Adds partial update guidance for Claude directory.

.claude/skills/zod/references/object-partial-for-updates.md

object-pick-omit.mdMirror Zod object-pick-omit into .claude +146/-0

Mirror Zod object-pick-omit into .claude

• Adds pick/omit guidance for Claude directory.

.claude/skills/zod/references/object-pick-omit.md

object-strict-vs-strip.mdMirror Zod object-strict-vs-strip into .claude +109/-0

Mirror Zod object-strict-vs-strip into .claude

• Adds strict vs strip guidance for Claude directory.

.claude/skills/zod/references/object-strict-vs-strip.md

parse-async-for-async-refinements.mdMirror Zod parse-async-for-async-refinements into .claude +118/-0

Mirror Zod parse-async-for-async-refinements into .claude

• Adds async parsing guidance for Claude directory.

.claude/skills/zod/references/parse-async-for-async-refinements.md

parse-avoid-double-validation.mdMirror Zod parse-avoid-double-validation into .claude +129/-0

Mirror Zod parse-avoid-double-validation into .claude

• Adds guidance to avoid double validation for Claude directory.

.claude/skills/zod/references/parse-avoid-double-validation.md

parse-handle-all-issues.mdMirror Zod parse-handle-all-issues into .claude +125/-0

Mirror Zod parse-handle-all-issues into .claude

• Adds handle-all-issues guidance for Claude directory.

.claude/skills/zod/references/parse-handle-all-issues.md

parse-never-trust-json.mdMirror Zod parse-never-trust-json into .claude +113...

@ivancidev
ivancidev merged commit cd59906 into main Jul 14, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants