Phase 7: SEO & Security Hardening
Optimize for search engines and harden application security before production.
Purpose
Phase 7 ensures the application is discoverable by search engines and protected against common security vulnerabilities. This phase must be completed before any production deployment. SEO drives organic traffic; security protects your users and data.
Actions
| Action |
Description |
Example |
start |
Begin Phase 7 |
$phase-7-seo-security start |
seo |
Implement SEO optimizations |
$phase-7-seo-security seo |
security |
Implement security hardening |
$phase-7-seo-security security |
audit |
Run SEO and security audit |
$phase-7-seo-security audit |
checklist |
Review compliance checklist |
$phase-7-seo-security checklist |
Deliverables
- Meta Tags Configuration - Title, description, Open Graph, Twitter Cards per page
- Sitemap & Robots - Dynamic sitemap.xml and robots.txt
- Structured Data - JSON-LD schemas (Organization, Article, Product, BreadcrumbList)
- Security Headers - CSP, HSTS, X-Frame-Options, X-Content-Type-Options
- Input Validation - Server-side validation on all endpoints
- OWASP Compliance - Top 10 vulnerability assessment and mitigation
- Accessibility Audit - WCAG AA compliance report
src/
├── app/
│ ├── layout.tsx # Root metadata and security headers
│ ├── robots.ts # Robots.txt generation
│ ├── sitemap.ts # Sitemap generation
│ └── manifest.ts # Web app manifest
├── middleware.ts # Security headers middleware
└── lib/
├── metadata.ts # Shared metadata helpers
└── sanitize.ts # Input sanitization utilities
docs/02-design/
├── seo-spec.md # SEO strategy document
└── security-spec.md # Security specifications
SEO Process
Step 1: Meta Tags
// app/layout.tsx
import type { Metadata } from 'next';
export const metadata: Metadata = {
metadataBase: new URL('https://example.com'),
title: { default: 'My App - Tagline', template: '%s | My App' },
description: 'Application description for search engines (150-160 chars).',
keywords: ['keyword1', 'keyword2', 'keyword3'],
openGraph: {
type: 'website', locale: 'en_US', url: 'https://example.com',
siteName: 'My App',
images: [{ url: '/og-image.png', width: 1200, height: 630, alt: 'My App' }],
},
twitter: { card: 'summary_large_image', creator: '@handle' },
robots: { index: true, follow: true,
googleBot: { index: true, follow: true, 'max-image-preview': 'large' } },
};
Step 2: Sitemap & Robots
// app/sitemap.ts
export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
const posts = await getAllPosts();
return [
{ url: 'https://example.com', lastModified: new Date(), changeFrequency: 'daily', priority: 1.0 },
{ url: 'https://example.com/about', lastModified: new Date(), changeFrequency: 'monthly', priority: 0.8 },
...posts.map((post) => ({
url: `https://example.com/blog/${post.slug}`,
lastModified: post.updatedAt, changeFrequency: 'weekly' as const, priority: 0.7,
})),
];
}
// app/robots.ts
export default function robots(): MetadataRoute.Robots {
return {
rules: [{ userAgent: '*', allow: '/', disallow: ['/api/', '/admin/', '/_next/'] }],
sitemap: 'https://example.com/sitemap.xml',
};
}
Step 3: Structured Data (JSON-LD)
export function ArticleJsonLd({ post }: { post: Post }) {
const schema = {
'@context': 'https://schema.org', '@type': 'Article',
headline: post.title, description: post.excerpt, image: post.coverImage,
datePublished: post.publishedAt, dateModified: post.updatedAt,
author: { '@type': 'Person', name: post.author.name },
};
return <script type="application/ld+json" dangerouslySetInnerHTML={{ __html: JSON.stringify(schema) }} />;
}
Step 4: Core Web Vitals
| Metric |
Target |
Optimization Strategy |
| LCP |
< 2.5s |
Optimize images (next/image), preload fonts, SSR critical pages |
| INP |
< 200ms |
Code splitting, minimize main thread work, defer non-critical JS |
| CLS |
< 0.1 |
Set explicit image dimensions, font-display: swap, reserve space |
Security Process
Step 5: Security Headers Middleware
// middleware.ts
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
export function middleware(request: NextRequest) {
const response = NextResponse.next();
const h = response.headers;
h.set('X-Frame-Options', 'DENY');
h.set('X-Content-Type-Options', 'nosniff');
h.set('Referrer-Policy', 'strict-origin-when-cross-origin');
h.set('Strict-Transport-Security', 'max-age=63072000; includeSubDomains; preload');
h.set('Permissions-Policy', 'camera=(), microphone=(), geolocation=()');
h.set('Content-Security-Policy', [
"default-src 'self'", "script-src 'self' 'unsafe-inline' 'unsafe-eval'",
"style-src 'self' 'unsafe-inline'", "img-src 'self' data: https:",
"font-src 'self'", "connect-src 'self' https://api.example.com",
"frame-ancestors 'none'",
].join('; '));
return response;
}
Step 6: OWASP Top 10 Compliance
| # |
Vulnerability |
Prevention |
Implementation |
| A01 |
Broken Access Control |
Role-based checks on every route and API |
Middleware + API guards |
| A02 |
Cryptographic Failures |
HTTPS everywhere, bcrypt for passwords |
TLS, env variables |
| A03 |
Injection |
Parameterized queries, Zod validation |
ORM + schema validation |
| A04 |
Insecure Design |
Threat modeling, least privilege |
Design review in Phase 8 |
| A05 |
Security Misconfiguration |
Remove defaults, minimal permissions |
Middleware + config audit |
| A06 |
Vulnerable Components |
npm audit, Dependabot |
CI pipeline checks |
| A07 |
Auth Failures |
Rate limiting, MFA, secure sessions |
Auth middleware + rate limiter |
| A08 |
Data Integrity |
Input validation, signed JWTs |
Zod + JWT verification |
| A09 |
Logging Failures |
Structured logging, anomaly alerts |
Logger + monitoring |
| A10 |
SSRF |
URL allowlists, validate user URLs |
Input validation |
Step 7: Input Validation and Sanitization
// lib/sanitize.ts
import { z } from 'zod';
import DOMPurify from 'isomorphic-dompurify';
export function sanitizeHtml(dirty: string): string {
return DOMPurify.sanitize(dirty, { ALLOWED_TAGS: ['b', 'i', 'em', 'strong', 'a', 'p', 'br'] });
}
export const emailSchema = z.string().email().max(255).toLowerCase().trim();
export const nameSchema = z.string().min(2).max(100).trim();
export const urlSchema = z.string().url().max(2048);
export const slugSchema = z.string().regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/).max(200);
SEO Checklist
Security Checklist
Level-wise Application
| Level |
SEO Scope |
Security Scope |
| Starter |
Basic meta tags, robots.txt |
Minimal (static site security) |
| Dynamic |
Full SEO + sitemap + JSON-LD + Core Web Vitals |
Full OWASP basics, auth security, input validation |
| Enterprise |
Full SEO + multi-language + schema.org + analytics |
Full OWASP, WAF, penetration testing, SOC2 compliance |
Security Patterns
See references/security-checklist.md for detailed patterns:
- Security headers reference
- OWASP Top 10 prevention matrix
- Input validation patterns
- Dependency audit procedures
PDCA Application
- Plan: Audit current SEO and security posture
- Design: Define optimization strategy and security requirements
- Do: Implement SEO metadata, security headers, input validation
- Check: Run Lighthouse audit, OWASP ZAP scan, dependency audit
- Act: Fix identified issues and proceed to Phase 8
Common Mistakes
| Mistake |
Solution |
| Missing meta descriptions |
Add unique descriptions to every page |
| Blocking search engines |
Check robots.txt is not blocking public pages |
| Exposing stack traces |
Return generic error messages in production |
| Hardcoded secrets |
Use environment variables exclusively |
| No rate limiting |
Add rate limiting to login and API endpoints |
| Ignoring dependency vulnerabilities |
Run npm audit in CI pipeline |
Output Location
docs/02-design/
├── seo-spec.md # SEO strategy and implementation
└── security-spec.md # Security specifications and audit results
Next Phase
When SEO and security hardening is complete, proceed to $phase-8-review for comprehensive code and architecture review.
1---2name: phase-7-seo-security-33description: Phase 7: SEO & Security. Implement search engine optimization, security hardening, and OWASP Top 10 compliance. Triggers: SEO, security, OWASP, XSS, CSRF, meta tags, sitemap, 보안, 검색엔진, セキュリティ, SEO, 安全, SEO, seguridad, sécurité, Sicherheit, sicurezza Do NOT use for: API auth design (use $phase-4-api), deployment (use $phase-9-deployment). Next: $phase-8-review4---56# Phase 7: SEO & Security Hardening78> Optimize for search engines and harden application security before production.910## Purpose1112Phase 7 ensures the application is discoverable by search engines and protected against common security vulnerabilities. This phase must be completed before any production deployment. SEO drives organic traffic; security protects your users and data.1314## Actions1516| Action | Description | Example |17|--------|-------------|---------|18| `start` | Begin Phase 7 | `$phase-7-seo-security start` |19| `seo` | Implement SEO optimizations | `$phase-7-seo-security seo` |20| `security` | Implement security hardening | `$phase-7-seo-security security` |21| `audit` | Run SEO and security audit | `$phase-7-seo-security audit` |22| `checklist` | Review compliance checklist | `$phase-7-seo-security checklist` |2324## Deliverables25261. **Meta Tags Configuration** - Title, description, Open Graph, Twitter Cards per page272. **Sitemap & Robots** - Dynamic sitemap.xml and robots.txt283. **Structured Data** - JSON-LD schemas (Organization, Article, Product, BreadcrumbList)294. **Security Headers** - CSP, HSTS, X-Frame-Options, X-Content-Type-Options305. **Input Validation** - Server-side validation on all endpoints316. **OWASP Compliance** - Top 10 vulnerability assessment and mitigation327. **Accessibility Audit** - WCAG AA compliance report3334```35src/36├── app/37│ ├── layout.tsx # Root metadata and security headers38│ ├── robots.ts # Robots.txt generation39│ ├── sitemap.ts # Sitemap generation40│ └── manifest.ts # Web app manifest41├── middleware.ts # Security headers middleware42└── lib/43 ├── metadata.ts # Shared metadata helpers44 └── sanitize.ts # Input sanitization utilities45docs/02-design/46├── seo-spec.md # SEO strategy document47└── security-spec.md # Security specifications48```4950## SEO Process5152### Step 1: Meta Tags5354```tsx55// app/layout.tsx56import type { Metadata } from 'next';5758export const metadata: Metadata = {59 metadataBase: new URL('https://example.com'),60 title: { default: 'My App - Tagline', template: '%s | My App' },61 description: 'Application description for search engines (150-160 chars).',62 keywords: ['keyword1', 'keyword2', 'keyword3'],63 openGraph: {64 type: 'website', locale: 'en_US', url: 'https://example.com',65 siteName: 'My App',66 images: [{ url: '/og-image.png', width: 1200, height: 630, alt: 'My App' }],67 },68 twitter: { card: 'summary_large_image', creator: '@handle' },69 robots: { index: true, follow: true,70 googleBot: { index: true, follow: true, 'max-image-preview': 'large' } },71};72```7374### Step 2: Sitemap & Robots7576```tsx77// app/sitemap.ts78export default async function sitemap(): Promise<MetadataRoute.Sitemap> {79 const posts = await getAllPosts();80 return [81 { url: 'https://example.com', lastModified: new Date(), changeFrequency: 'daily', priority: 1.0 },82 { url: 'https://example.com/about', lastModified: new Date(), changeFrequency: 'monthly', priority: 0.8 },83 ...posts.map((post) => ({84 url: `https://example.com/blog/${post.slug}`,85 lastModified: post.updatedAt, changeFrequency: 'weekly' as const, priority: 0.7,86 })),87 ];88}8990// app/robots.ts91export default function robots(): MetadataRoute.Robots {92 return {93 rules: [{ userAgent: '*', allow: '/', disallow: ['/api/', '/admin/', '/_next/'] }],94 sitemap: 'https://example.com/sitemap.xml',95 };96}97```9899### Step 3: Structured Data (JSON-LD)100101```tsx102export function ArticleJsonLd({ post }: { post: Post }) {103 const schema = {104 '@context': 'https://schema.org', '@type': 'Article',105 headline: post.title, description: post.excerpt, image: post.coverImage,106 datePublished: post.publishedAt, dateModified: post.updatedAt,107 author: { '@type': 'Person', name: post.author.name },108 };109 return <script type="application/ld+json" dangerouslySetInnerHTML={{ __html: JSON.stringify(schema) }} />;110}111```112113### Step 4: Core Web Vitals114115| Metric | Target | Optimization Strategy |116|--------|--------|----------------------|117| LCP | < 2.5s | Optimize images (next/image), preload fonts, SSR critical pages |118| INP | < 200ms | Code splitting, minimize main thread work, defer non-critical JS |119| CLS | < 0.1 | Set explicit image dimensions, font-display: swap, reserve space |120121## Security Process122123### Step 5: Security Headers Middleware124125```typescript126// middleware.ts127import { NextResponse } from 'next/server';128import type { NextRequest } from 'next/server';129130export function middleware(request: NextRequest) {131 const response = NextResponse.next();132 const h = response.headers;133 h.set('X-Frame-Options', 'DENY');134 h.set('X-Content-Type-Options', 'nosniff');135 h.set('Referrer-Policy', 'strict-origin-when-cross-origin');136 h.set('Strict-Transport-Security', 'max-age=63072000; includeSubDomains; preload');137 h.set('Permissions-Policy', 'camera=(), microphone=(), geolocation=()');138 h.set('Content-Security-Policy', [139 "default-src 'self'", "script-src 'self' 'unsafe-inline' 'unsafe-eval'",140 "style-src 'self' 'unsafe-inline'", "img-src 'self' data: https:",141 "font-src 'self'", "connect-src 'self' https://api.example.com",142 "frame-ancestors 'none'",143 ].join('; '));144 return response;145}146```147148### Step 6: OWASP Top 10 Compliance149150| # | Vulnerability | Prevention | Implementation |151|---|--------------|------------|----------------|152| A01 | Broken Access Control | Role-based checks on every route and API | Middleware + API guards |153| A02 | Cryptographic Failures | HTTPS everywhere, bcrypt for passwords | TLS, env variables |154| A03 | Injection | Parameterized queries, Zod validation | ORM + schema validation |155| A04 | Insecure Design | Threat modeling, least privilege | Design review in Phase 8 |156| A05 | Security Misconfiguration | Remove defaults, minimal permissions | Middleware + config audit |157| A06 | Vulnerable Components | npm audit, Dependabot | CI pipeline checks |158| A07 | Auth Failures | Rate limiting, MFA, secure sessions | Auth middleware + rate limiter |159| A08 | Data Integrity | Input validation, signed JWTs | Zod + JWT verification |160| A09 | Logging Failures | Structured logging, anomaly alerts | Logger + monitoring |161| A10 | SSRF | URL allowlists, validate user URLs | Input validation |162163### Step 7: Input Validation and Sanitization164165```typescript166// lib/sanitize.ts167import { z } from 'zod';168import DOMPurify from 'isomorphic-dompurify';169170export function sanitizeHtml(dirty: string): string {171 return DOMPurify.sanitize(dirty, { ALLOWED_TAGS: ['b', 'i', 'em', 'strong', 'a', 'p', 'br'] });172}173174export const emailSchema = z.string().email().max(255).toLowerCase().trim();175export const nameSchema = z.string().min(2).max(100).trim();176export const urlSchema = z.string().url().max(2048);177export const slugSchema = z.string().regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/).max(200);178```179180## SEO Checklist181182- [ ] Title tag on every page (50-60 characters)183- [ ] Meta description on every page (150-160 characters)184- [ ] Open Graph tags (title, description, image, type)185- [ ] Twitter Card tags186- [ ] Canonical URLs set187- [ ] sitemap.xml with all public pages188- [ ] robots.txt with appropriate rules189- [ ] JSON-LD structured data190- [ ] Image alt texts on all images191- [ ] Semantic HTML (h1-h6 hierarchy, nav, main, article)192- [ ] Core Web Vitals passing (LCP < 2.5s, INP < 200ms, CLS < 0.1)193194## Security Checklist195196- [ ] HTTPS enforced (HSTS header)197- [ ] Security headers configured (CSP, X-Frame-Options, etc.)198- [ ] All user inputs validated server-side (Zod)199- [ ] HTML content sanitized (DOMPurify)200- [ ] SQL injection prevented (parameterized queries/ORM)201- [ ] XSS prevention (React auto-escaping + CSP)202- [ ] CSRF protection (SameSite cookies, CSRF tokens)203- [ ] Rate limiting on auth endpoints204- [ ] Dependencies audited (npm audit)205- [ ] Secrets in environment variables (not in code)206- [ ] CORS properly configured207- [ ] Error messages do not leak implementation details208209## Level-wise Application210211| Level | SEO Scope | Security Scope |212|-------|-----------|----------------|213| Starter | Basic meta tags, robots.txt | Minimal (static site security) |214| Dynamic | Full SEO + sitemap + JSON-LD + Core Web Vitals | Full OWASP basics, auth security, input validation |215| Enterprise | Full SEO + multi-language + schema.org + analytics | Full OWASP, WAF, penetration testing, SOC2 compliance |216217## Security Patterns218219See `references/security-checklist.md` for detailed patterns:220- Security headers reference221- OWASP Top 10 prevention matrix222- Input validation patterns223- Dependency audit procedures224225## PDCA Application226227- **Plan**: Audit current SEO and security posture228- **Design**: Define optimization strategy and security requirements229- **Do**: Implement SEO metadata, security headers, input validation230- **Check**: Run Lighthouse audit, OWASP ZAP scan, dependency audit231- **Act**: Fix identified issues and proceed to Phase 8232233## Common Mistakes234235| Mistake | Solution |236|---------|----------|237| Missing meta descriptions | Add unique descriptions to every page |238| Blocking search engines | Check robots.txt is not blocking public pages |239| Exposing stack traces | Return generic error messages in production |240| Hardcoded secrets | Use environment variables exclusively |241| No rate limiting | Add rate limiting to login and API endpoints |242| Ignoring dependency vulnerabilities | Run npm audit in CI pipeline |243244## Output Location245246```247docs/02-design/248├── seo-spec.md # SEO strategy and implementation249└── security-spec.md # Security specifications and audit results250```251252## Next Phase253254When SEO and security hardening is complete, proceed to **$phase-8-review** for comprehensive code and architecture review.