Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Enhance SEO (meta tags, semantic HTML) and security (vulnerability checks, hardening). Triggers: SEO, security, meta tags, vulnerability, 검색 최적화, 보안.
.claude/skills/popup-studio-ai-phase-7-seo-security/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-01 | ✗→✓ | ▲ Improved | 35% | 0% |
| case-03 | ✗→✓ | ▲ Improved | 94% | 0% |
| case-10 | ✗→✓ | ▲ Improved | 80% | 0% |
| case-11 | ✗→✓ | ▲ Improved | 60% | 0% |
| case-12 | ✗→✓ | ▲ Improved | 207% | 0% |
> Search optimization and security enhancement
Make the application discoverable through search and defend against security vulnerabilities.
docs/02-design/
├── seo-spec.md # SEO specification
└── security-spec.md # Security specification
src/
├── middleware/ # Security middleware
└── components/
└── seo/ # SEO components| Level | Application Method | |-------|-------------------| | Starter | SEO only (minimal security) | | Dynamic | SEO + basic security | | Enterprise | SEO + advanced security |
┌─────────────────────────────────────────────────────────────┐
│ Client (Browser) │
├─────────────────────────────────────────────────────────────┤
│ Phase 6: UI Security │
│ - XSS defense (input escaping) │
│ - CSRF token inclusion │
│ - No sensitive info storage on client │
├─────────────────────────────────────────────────────────────┤
│ Phase 4/6: API Communication Security │
│ - HTTPS enforcement │
│ - Authorization header (Bearer Token) │
│ - Content-Type validation │
├─────────────────────────────────────────────────────────────┤
│ Phase 4: API Server Security │
│ - Input validation │
│ - Rate Limiting │
│ - Minimal error messages (prevent sensitive info exposure) │
├─────────────────────────────────────────────────────────────┤
│ Phase 2/9: Environment Variable Security │
│ - Secrets management │
│ - Environment separation │
│ - Client-exposed variable distinction │
└─────────────────────────────────────────────────────────────┘| Phase | Security Responsibility | Verification Items | |-------|------------------------|-------------------| | Phase 2 | Environment variable convention | NEXT_PUBLIC_ distinction, Secrets list | | Phase 4 | API security design | Auth method, error codes, input validation | | Phase 6 | Client security | XSS defense, token management, sensitive info | | Phase 7 | Security implementation/inspection | Full security checklist | | Phase 9 | Deployment security | Secrets injection, HTTPS, security headers |
⚠️ XSS (Cross-Site Scripting) Defense
1. Never use innerHTML directly
2. Always sanitize user input when rendering as HTML
3. Leverage React's automatic escaping
4. Use DOMPurify library when neededtypescript// ❌ Forbidden: Sensitive info in localStorage localStorage.setItem('password', password); localStorage.setItem('creditCard', cardNumber); // ✅ Allowed: Store only tokens (httpOnly cookies recommended) localStorage.setItem('auth_token', token); // ✅ More secure: httpOnly cookie (set by server) // Set-Cookie: token=xxx; HttpOnly; Secure; SameSite=Strict
typescript// Include CSRF token in API client // lib/api/client.ts private async request<T>(endpoint: string, config: RequestConfig = {}) { const headers = new Headers(config.headers); // Add CSRF token const csrfToken = this.getCsrfToken(); if (csrfToken) { headers.set('X-CSRF-Token', csrfToken); } // ... }
typescript// All input must be validated on the server import { z } from 'zod'; const CreateUserSchema = z.object({ email: z.string().email(), password: z.string().min(8).max(100), name: z.string().min(1).max(50), }); // Usage in API Route export async function POST(req: Request) { const body = await req.json(); const result = CreateUserSchema.safeParse(body); if (!result.success) { return Response.json({ error: { code: 'VALIDATION_ERROR', message: 'Input is invalid.', details: result.error.flatten().fieldErrors, } }, { status: 400 }); } const { email, password, name } = result.data; }
typescript// ❌ Dangerous: Detailed error info exposure { message: 'User with email test@test.com not found', stack: error.stack, // Stack trace exposed! } // ✅ Safe: Minimal information only { code: 'NOT_FOUND', message: 'User not found.', } // Detailed logs only on server console.error(`User not found: ${email}`, error);
typescript// middleware.ts import { Ratelimit } from '@upstash/ratelimit'; const ratelimit = new Ratelimit({ redis: Redis.fromEnv(), limiter: Ratelimit.slidingWindow(10, '10 s'), }); export async function middleware(request: NextRequest) { const ip = request.ip ?? '127.0.0.1'; const { success } = await ratelimit.limit(ip); if (!success) { return new Response('Too Many Requests', { status: 429 }); } }
typescript// lib/env.ts const serverEnvSchema = z.object({ DATABASE_URL: z.string(), // Server only AUTH_SECRET: z.string(), // Server only }); const clientEnvSchema = z.object({ NEXT_PUBLIC_APP_URL: z.string(), // Can be exposed to client }); export const serverEnv = serverEnvSchema.parse(process.env); export const clientEnv = clientEnvSchema.parse({ NEXT_PUBLIC_APP_URL: process.env.NEXT_PUBLIC_APP_URL, });
javascript// next.config.js const securityHeaders = [ { key: 'Strict-Transport-Security', value: 'max-age=63072000' }, { key: 'X-Frame-Options', value: 'SAMEORIGIN' }, { key: 'X-Content-Type-Options', value: 'nosniff' }, { key: 'Referrer-Policy', value: 'origin-when-cross-origin' }, ]; module.exports = { async headers() { return [{ source: '/:path*', headers: securityHeaders }]; }, };
tsx// app/layout.tsx export const metadata: Metadata = { title: { default: 'Site Name', template: '%s | Site Name', }, description: 'Site description', openGraph: { type: 'website', locale: 'en_US', url: 'https://example.com', siteName: 'Site Name', }, };
See templates/pipeline/phase-7-seo-security.template.md
Phase 8: Review → After optimization, verify overall code quality
Other measured skills in the registry, with their headline benchmark lift.