diff --git a/README.md b/README.md index 570e9c0..98284ab 100644 --- a/README.md +++ b/README.md @@ -14,17 +14,27 @@ I'd love to hear your thoughts! If you have suggestions or find any bugs: There are four skills in this project. Each one lives in its own folder and contains a `SKILL.md` file. -### 1. taste-skill -The main design skill. Teaches the AI how to write good-looking frontend code from scratch. Covers layout, typography, colors, spacing, motion, and overall visual quality. +### 1. taste-skill (14 sections) +The main design skill. Teaches the AI how to write good-looking frontend code from scratch. Covers layout, typography, colors, spacing, motion, and overall visual quality. **Now includes:** accessibility (WCAG 2.2 AA), Core Web Vitals performance, responsive images, dark/light mode system, SEO meta architecture, and 4 before/after code examples. ### 2. redesign-skill -For upgrading existing projects. Instead of rebuilding from zero, this skill walks the AI through auditing what's already there and fixing the biggest design problems first. +For upgrading existing projects. Instead of rebuilding from zero, this skill walks the AI through auditing what's already there and fixing the biggest design problems first. **Now includes:** accessibility audit, Core Web Vitals audit, SEO audit, and an expanded 10-step fix priority. -### 3. soft-skill -Focuses on making things look and feel expensive. Covers premium fonts, big breathing whitespace, layered card designs with depth, smooth spring-based animations, and floating navigation. Bans all the generic defaults that make AI output look like a template. +### 3. soft-skill (11 sections) +Focuses on making things look and feel expensive. Use for luxury, editorial, or Awwwards-tier builds. Covers premium fonts, big breathing whitespace, layered card designs with depth, smooth spring-based animations, and floating navigation. Bans all the generic defaults that make AI output look like a template. **Now includes:** accessibility, dark/light mode, SEO & performance, and a clear "when to use this vs taste-skill" guide. ### 4. output-skill -Stops the AI from being lazy. Prevents placeholder comments, skipped code blocks, and half-finished outputs. Forces the AI to actually write everything instead of cutting corners. +Stops the AI from being lazy. Prevents placeholder comments, skipped code blocks, and half-finished outputs. Forces the AI to actually write everything instead of cutting corners. **Now includes:** multi-file output handling and iterative request rules. + +### When to use which skill + +| Scenario | Skill | +|----------|-------| +| Building a new SaaS, dashboard, or web app | taste-skill | +| Building a luxury/editorial/agency site (Awwwards-tier) | soft-skill | +| Upgrading an existing project | redesign-skill | +| Any task requiring complete, untruncated output | output-skill | +| Production build | taste-skill + output-skill (combine both) | ## How to Use diff --git a/output-skill/SKILL.md b/output-skill/SKILL.md index d983bbc..de1ab76 100644 --- a/output-skill/SKILL.md +++ b/output-skill/SKILL.md @@ -40,6 +40,24 @@ When a response approaches the token limit: On "continue", pick up exactly where you stopped. No recap, no repetition. +## Multi-File Outputs + +When a task requires multiple files (e.g., "build a landing page with 5 components"): + +1. **Declare the file manifest** at the start. List every file you will create with its path. +2. **Output each file completely** with its full path as the code block label. +3. **Never merge files** to save space. Each file gets its own complete code block. +4. **Imports must resolve.** For files created or modified in this response, ensure import/export paths are valid. Do not duplicate untouched repository files just to satisfy imports. +5. **Include dependency commands.** If any file requires a package not in `package.json`, list all `npm install` commands at the top before any code. + +## Handling Iterative Requests + +When the user asks you to modify existing code: + +1. **Show the complete modified file** — not just the changed lines. Partial diffs are ambiguous and error-prone. +2. **If only a small section changed,** you may show the full file and highlight the changed region in surrounding prose (use inline comments only when the file format supports them) — but never omit unchanged code with `// ...`. +3. **If the user explicitly asks for "just the diff"** or "just the changed part," you may show only the changed section — but this is the ONLY exception. + ## Quick Check Before finalizing any response, verify: @@ -47,3 +65,5 @@ Before finalizing any response, verify: - Every item the user requested is present and finished - Code blocks contain actual runnable code, not descriptions of what code would do - Nothing was shortened to save space +- All imports across files resolve correctly +- Dependency install commands are included for any new packages diff --git a/redesign-skill/SKILL.md b/redesign-skill/SKILL.md index c8304f0..3eb7cbb 100644 --- a/redesign-skill/SKILL.md +++ b/redesign-skill/SKILL.md @@ -120,6 +120,41 @@ Check for these problems and fix them: - **Import hallucinations.** Check that every import actually exists in `package.json` or the project dependencies. - **Missing meta tags.** Add proper ``, `description`, `og:image`, and social sharing meta tags. +### Accessibility + +- **Missing `prefers-reduced-motion` support.** All animations, transitions, parallax, and auto-playing carousels must disable or simplify when reduced motion is requested. This is the most commonly missed accessibility rule in AI-generated code. +- **Poor color contrast.** Run all text/background pairs through a contrast checker. WCAG AA requires 4.5:1 for normal text, 3:1 for large text. Low-opacity text on subtle backgrounds usually fails. +- **No focus indicators.** Every interactive element needs a visible `focus-visible` ring. Never set `outline: none` without a replacement. +- **Missing ARIA labels.** Icon-only buttons, hamburger menus, close buttons, social links — all need `aria-label`. +- **No skip-to-content link.** Add a hidden link that becomes visible on focus for keyboard users. +- **Color used alone for meaning.** Error states, status indicators, and validation all need icons or text in addition to color. +- **Missing `alt` text.** Every meaningful image needs descriptive alt text. Decorative images should have `alt=""` and `role="presentation"`. +- **No keyboard trap handling.** Modals should trap focus when open and restore on close; menus should allow Tab/Shift+Tab to move away and Escape to close. +- **Form inputs without labels.** Every `<input>` needs a visible `<label>` with matching `htmlFor`/`id`. Placeholder text is not a label. + +### Performance (Core Web Vitals) + +- **No image optimization.** Replace raw PNGs/JPGs with Next.js `<Image>`, `<picture>` with `srcset`, or WebP/AVIF formats. Set explicit `width` and `height` to prevent CLS. +- **Hero image not preloaded.** Add `priority` (Next.js Image) or `<link rel="preload">` for the largest above-the-fold image. Target LCP < 2.5s. +- **Fonts not preloaded.** Custom fonts cause FOUT/FOIT. Use `<link rel="preload" as="font" crossorigin>` for critical fonts. Use `font-display: swap`. +- **No lazy loading below the fold.** Every image and heavy component below the fold should use `loading="lazy"` or `next/dynamic`. +- **Oversized JavaScript bundle.** Check if Framer Motion (~57KB gz), GSAP (~25KB gz), or other animation libraries are imported but barely used. Tree-shake or dynamically import. +- **Animations using layout-triggering properties.** `top`, `left`, `width`, `height` cause reflows. Switch to `transform` and `opacity`. +- **No CLS prevention.** Images without dimensions, dynamically injected banners, and late-loading fonts all cause layout shift. Reserve space with skeletons. +- **Missing `will-change` cleanup.** If `will-change: transform` is applied, it must be removed when animation completes. + +### SEO + +- **Missing or generic `<title>` tags.** Each page needs a unique, keyword-rich title under 60 characters. +- **No meta description.** Add `<meta name="description">` under 160 characters per page. +- **Missing Open Graph tags.** Add `og:title`, `og:description`, `og:image` (1200x630px), `og:url` for every public page. +- **No canonical URL.** Add `<link rel="canonical">` to prevent duplicate content issues. +- **Missing sitemap.xml and robots.txt.** Generate and serve both. Use the project's framework conventions (e.g., Next.js App Router: `app/sitemap.ts` and `app/robots.ts`; Pages Router/static setups: serve from `public/sitemap.xml` and `public/robots.txt`). +- **Heading hierarchy broken.** One `<h1>` per page. Never skip levels (h1 → h3). Screen readers and crawlers use heading structure. +- **No structured data (JSON-LD).** Add schema markup for Organization, Product, FAQ, BreadcrumbList as appropriate. +- **Critical content hidden behind JavaScript.** Hero text, navigation, and primary CTAs must be server-rendered, not loaded client-side. +- **Images without alt text.** Google indexes alt text. Be descriptive and specific, not generic. + ### Strategic Omissions (What AI Typically Forgets) - **No legal links.** Add privacy policy and terms of service links in the footer. @@ -162,11 +197,14 @@ Apply changes in this order for maximum visual impact with minimum risk: 1. **Font swap** — biggest instant improvement, lowest risk 2. **Color palette cleanup** — remove clashing or oversaturated colors -3. **Hover and active states** — makes the interface feel alive -4. **Layout and spacing** — proper grid, max-width, consistent padding -5. **Replace generic components** — swap cliche patterns for modern alternatives -6. **Add loading, empty, and error states** — makes it feel finished -7. **Polish typography scale and spacing** — the premium final touch +3. **Accessibility fixes** — contrast, focus rings, reduced motion, ARIA labels +4. **Hover and active states** — makes the interface feel alive +5. **Layout and spacing** — proper grid, max-width, consistent padding +6. **Image optimization & performance** — responsive images, preloads, lazy loading +7. **Replace generic components** — swap cliche patterns for modern alternatives +8. **Add loading, empty, and error states** — makes it feel finished +9. **SEO meta tags & structured data** — discoverability and social sharing +10. **Polish typography scale and spacing** — the premium final touch ## Rules diff --git a/soft-skill/SKILL.md b/soft-skill/SKILL.md index 4038f41..28f1c24 100644 --- a/soft-skill/SKILL.md +++ b/soft-skill/SKILL.md @@ -5,9 +5,12 @@ description: Teaches the AI to design like a high-end agency. Defines the exact # Agent Skill: Principal UI/UX Architect & Motion Choreographer (Awwwards-Tier) +## 0. WHEN TO USE THIS SKILL +Use **soft-skill** when building luxury, editorial, or agency-tier experiences where the visual bar is "Awwwards Site of the Day." Use **taste-skill** for general-purpose premium interfaces (SaaS, dashboards, standard web apps). When in doubt, start with taste-skill — it covers 90% of cases. Soft-skill is the upgrade path for projects where the client specifically demands "make it feel expensive." + ## 1. Meta Information & Core Directive - **Persona:** `Vanguard_UI_Architect` -- **Objective:** You engineer $150k+ agency-level digital experiences, not just websites. Your output must exude haptic depth, cinematic spatial rhythm, obsessive micro-interactions, and flawless fluid motion. +- **Objective:** You engineer $150k+ agency-level digital experiences, not just websites. Your output must exude haptic depth, cinematic spatial rhythm, obsessive micro-interactions, and flawless fluid motion. - **The Variance Mandate:** NEVER generate the exact same layout or aesthetic twice in a row. You must dynamically combine different premium layout archetypes and texture profiles while strictly adhering to the elite "Apple-esque / Linear-tier" design language. ## 2. THE "ABSOLUTE ZERO" DIRECTIVE (STRICT ANTI-PATTERNS) @@ -83,7 +86,33 @@ When generating UI code, follow this exact sequence: 4. **[CHOREOGRAPH]** Inject the custom `cubic-bezier` transitions, the staggered navigation reveals, and the button-in-button hover physics. 5. **[OUTPUT]** Deliver flawless, pixel-perfect React/Tailwind/HTML code. Do not include basic, generic fallbacks. -## 8. PRE-OUTPUT CHECKLIST +## 8. ACCESSIBILITY (NON-NEGOTIABLE) +Premium is not premium if 15% of users cannot use it. Apply these rules without exception: +* **Contrast:** All text must meet WCAG 2.2 AA (4.5:1 normal, 3:1 large). Ethereal Glass vibes with low-opacity text are beautiful but fail contrast — increase foreground/background contrast by adjusting text color, opacity, or surface color; only use weight/size to qualify as "large text" (3:1 ratio). +* **Reduced Motion:** Wrap ALL Framer Motion, GSAP, and CSS animations in `prefers-reduced-motion` checks. Spring physics, parallax, scroll hijacks — all must degrade to instant transitions when reduced motion is active. Use stack-appropriate detection: CSS `@media (prefers-reduced-motion: reduce)`, `window.matchMedia` in JS/GSAP, or `useReducedMotion()` only when Framer Motion is already in use. For a complete Framer Motion implementation example, see taste-skill Section 10 (ReducedMotionWrapper.tsx). +* **Focus Indicators:** Every clickable element needs a visible `focus-visible` ring. Never use `outline-none` without an alternative. +* **Keyboard Navigation:** Full Tab flow through all interactive elements. Focus traps limited to true modals. Hamburger menus must allow Escape to close and Tab to exit naturally. +* **ARIA:** Icon-only buttons need `aria-label`. Dynamic content (toasts, counters) needs `aria-live`. Form inputs need linked `<label>` elements. +* **Skip Link:** First focusable element must be "Skip to main content" — hidden until focused. +* **Semantic HTML:** `<nav>`, `<main>`, `<article>`, `<section>`, `<aside>`, `<header>`, `<footer>` — not div soup. +* **Color Independence:** Never use color alone for meaning. Status dots need text labels. Error inputs need icons + descriptive text. + +## 9. DARK/LIGHT MODE +* Default to `prefers-color-scheme` detection on first visit. Store override in `localStorage`. Prevent theme flash with a blocking `<script>` in `<head>`. +* **Dark mode is not inverted light mode.** Higher surfaces = lighter backgrounds (`#141414` → `#1c1c1c` → `#262626`). Reduce text contrast slightly (`#e4e4e7` body, not pure `#ffffff`). +* **Shadows in dark mode** should be deeper (`rgba(0,0,0,0.5)`) and more diffused. +* **Images:** Apply `brightness(0.9)` to photos in dark mode to prevent eye strain. +* Use CSS custom properties as the single source of truth for all color values. + +## 10. SEO & PERFORMANCE +* **Core Web Vitals:** LCP < 2.5s (preload hero image, fonts), CLS < 0.1 (explicit image dimensions), INP < 200ms (debounce handlers). +* **Responsive Images:** Use `<Image>` (Next.js) or `<picture>` with `srcset`. Serve WebP/AVIF. Set explicit `sizes` attribute. +* **Bundle Size:** Framer Motion (~57KB gz) + GSAP (~25KB gz) — never import both unless genuinely needed. Dynamic import heavy components below the fold. +* **Meta Tags:** Every page needs `<title>`, `description`, `og:image`, `twitter:card`, canonical URL. Add JSON-LD structured data. +* **Semantic Headings:** One `<h1>` per page. Never skip levels. Server-render all critical text content. +* **Sitemap & Robots:** Generate `sitemap.xml` and `robots.txt`. Index all public pages. + +## 11. PRE-OUTPUT CHECKLIST Evaluate your code against this matrix before delivering. This is the last filter. - [ ] No banned fonts, icons, borders, shadows, layouts, or motion patterns from Section 2 are present - [ ] A Vibe Archetype and Layout Archetype from Section 3 were consciously selected and applied @@ -95,4 +124,11 @@ Evaluate your code against this matrix before delivering. This is the last filte - [ ] Layout collapses gracefully below `768px` to single-column with `w-full` and `px-4` - [ ] All animations use only `transform` and `opacity` — no layout-triggering properties - [ ] `backdrop-blur` is only applied to fixed/sticky elements, never to scrolling content +- [ ] ALL animations respect `prefers-reduced-motion` (Section 8) +- [ ] Color contrast meets WCAG AA ratios (4.5:1 normal, 3:1 large) (Section 8) +- [ ] Focus indicators visible on all interactive elements (Section 8) +- [ ] Semantic HTML used — no div soup (Section 8) +- [ ] Hero image preloaded, all images responsive with explicit dimensions (Section 10) +- [ ] Meta tags, OG image, canonical URL, and JSON-LD present (Section 10) +- [ ] Dark mode uses elevated surfaces, not inverted shadows (Section 9) - [ ] The overall impression reads as "$150k agency build", not "template with nice fonts" diff --git a/taste-skill/SKILL.md b/taste-skill/SKILL.md index ccc3a2f..19d003f 100644 --- a/taste-skill/SKILL.md +++ b/taste-skill/SKILL.md @@ -75,6 +75,16 @@ To actively combat generic AI designs, systematically implement these high-end c * **DOM Cost:** Apply grain/noise filters exclusively to fixed, pointer-event-none pseudo-elements (e.g., `fixed inset-0 z-50 pointer-events-none`) and NEVER to scrolling containers to prevent continuous GPU repaints and mobile performance degradation. * **Hardware Acceleration:** Never animate `top`, `left`, `width`, or `height`. Animate exclusively via `transform` and `opacity`. * **Z-Index Restraint:** NEVER spam arbitrary `z-50` or `z-10` unprompted. Use z-indexes strictly for systemic layer contexts (Sticky Navbars, Modals, Overlays). +* **Core Web Vitals [MANDATORY]:** + * **LCP (Largest Contentful Paint) < 2.5s:** Hero images must use `<Image priority />` (Next.js) or `<link rel="preload">`. Lazy-load everything below the fold. Preload critical fonts with `<link rel="preload" as="font" crossorigin>`. + * **CLS (Cumulative Layout Shift) < 0.1:** Always set explicit `width` and `height` on images and media. Reserve space for async content with skeleton placeholders. Never inject content above existing content after load. + * **INP (Interaction to Next Paint) < 200ms:** Debounce scroll handlers. Use `startTransition` for non-urgent state updates. Offload heavy computation to Web Workers. +* **Bundle Awareness:** Framer Motion adds ~57KB gzipped. GSAP adds ~25KB. Do not import both unless the project genuinely needs both. Tree-shake unused Framer features (`import { motion } from "framer-motion"` not `import * as`). Use dynamic imports (`next/dynamic`) for heavy animation components below the fold. +* **Image Optimization [MANDATORY]:** + * Always use Next.js `<Image>` component or `<picture>` with `srcset` for responsive images. + * Serve WebP/AVIF with fallback. Never serve unoptimized PNGs for photos. + * Apply `loading="lazy"` to all images below the fold. Apply `fetchpriority="high"` to the hero image. + * Set explicit `sizes` attribute to prevent the browser from downloading oversized images (e.g., `sizes="(max-width: 768px) 100vw, 50vw"`). ## 6. TECHNICAL REFERENCE (Dial Definitions) @@ -215,7 +225,316 @@ Implement these specific micro-animations when constructing Bento grids (e.g., R 4. **The Wide Data Stream:** A horizontal "Infinite Carousel" of data cards or metrics. Ensure the loop is seamless (using `x: ["0%", "-100%"]`) with a speed that feels effortless. 5. **The Contextual UI (Focus Mode):** A document view that animates a staggered highlight of a text block, followed by a "Float-in" of a floating action toolbar with micro-icons. -## 10. FINAL PRE-FLIGHT CHECK +## 10. ACCESSIBILITY (WCAG 2.2 AA COMPLIANCE) +Premium design without accessibility is not premium — it is exclusionary. These rules are non-negotiable: + +### Color & Contrast +* **Contrast Ratios [MANDATORY]:** Normal text must meet 4.5:1 contrast ratio against its background. Large text (18px+ or 14px+ bold) must meet 3:1. Use browser DevTools or [WebAIM Contrast Checker](https://webaim.org/resources/contrastchecker/) to verify. +* **Never rely on color alone** to convey information. Error states need icons + text, not just red borders. Status indicators need labels, not just colored dots. +* **Color Blindness Safety:** Test designs against deuteranopia (red-green) and tritanopia (blue-yellow). Avoid red/green pairings for success/error — use green/red + icons, or use blue/orange as alternatives. + +### Motion & Vestibular Safety +* **`prefers-reduced-motion` [MANDATORY]:** ALL animations, transitions, parallax, and auto-playing content MUST respect this media query. Wrap Framer Motion in a check: +```tsx +// ReducedMotionWrapper.tsx +'use client'; +import { motion, useReducedMotion } from 'framer-motion'; + +export function AnimatedSection({ children }: { children: React.ReactNode }) { + const shouldReduce = useReducedMotion(); + return ( + <motion.div + initial={shouldReduce ? false : { opacity: 0, y: 20 }} + whileInView={shouldReduce ? {} : { opacity: 1, y: 0 }} + transition={shouldReduce ? { duration: 0 } : { type: 'spring', stiffness: 100, damping: 20 }} + > + {children} + </motion.div> + ); +} +``` +* **No auto-playing carousels** without a visible pause button. Infinite loops must stop when `prefers-reduced-motion: reduce` is set. +* **No scroll hijacking** (horizontal scroll takeover, locomotive scroll) without a bypass mechanism. + +### Keyboard & Screen Reader +* **Focus Management:** Every interactive element must be reachable via Tab. Custom focus rings must be visible — use `focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-blue-500`. Never use `outline-none` without a replacement. +* **Skip Navigation [MANDATORY]:** Add a hidden "Skip to main content" link as the first focusable element: +```tsx +<a href="#main" className="sr-only focus:not-sr-only focus:fixed focus:top-4 focus:left-4 focus:z-[100] focus:px-4 focus:py-2 focus:bg-white focus:text-black focus:rounded-lg"> + Skip to main content +</a> +``` +* **ARIA Labels:** Interactive elements without visible text MUST have `aria-label`. Icon-only buttons, hamburger menus, close buttons, social links — all need labels. +* **Semantic HTML:** Use `<nav>`, `<main>`, `<article>`, `<section>`, `<aside>`, `<header>`, `<footer>`. Landmarks enable screen reader users to jump between page regions. +* **Live Regions:** Dynamic content (toast notifications, form errors, live counters) must use `aria-live="polite"` or `aria-live="assertive"` so screen readers announce changes. + +### Forms +* **Labels are non-negotiable.** Every `<input>` must have a visible `<label>` with matching `htmlFor`/`id`. Placeholder text is NOT a label. +* **Error messages** must be linked to inputs via `aria-describedby` and the input must have `aria-invalid="true"`. +* **Required fields** must use `aria-required="true"` in addition to visual indicators. + +## 11. DARK/LIGHT MODE SYSTEM +When building interfaces that support both modes, follow this systematic approach: + +### Architecture +* **CSS Custom Properties as single source of truth.** Define all colors as CSS variables in `:root` (light) and `.dark` or `[data-theme="dark"]` (dark). Never hardcode hex values in components. +```css +/* globals.css */ +:root { + --bg-primary: #fafafa; + --bg-secondary: #ffffff; + --text-primary: #0a0a0a; + --text-secondary: #525252; + --border: rgba(0, 0, 0, 0.06); + --shadow-color: rgba(0, 0, 0, 0.04); + --accent: #0ea5e9; +} + +.dark { + --bg-primary: #0a0a0a; + --bg-secondary: #141414; + --text-primary: #fafafa; + --text-secondary: #a1a1aa; + --border: rgba(255, 255, 255, 0.06); + --shadow-color: rgba(0, 0, 0, 0.3); + --accent: #38bdf8; +} +``` +* **Tailwind Integration:** Use Tailwind's `dark:` variant. Configure `darkMode: 'class'` in Tailwind config. Apply `dark` class to `<html>` element. +* **System Preference Detection:** Default to `prefers-color-scheme` on first visit. Store user override in `localStorage`. Prevent flash of wrong theme with a blocking `<script>` in `<head>`: +```html +<script> + const theme = localStorage.getItem('theme') || + (matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'); + document.documentElement.classList.toggle('dark', theme === 'dark'); +</script> +``` + +### Design Rules for Dark Mode +* **Never invert colors 1:1.** Dark mode is not "light mode with colors swapped." Reduce contrast slightly — `#fafafa` text on `#0a0a0a` is too harsh. Use `#e4e4e7` on `#0a0a0a` for body text. +* **Elevate with lightness, not shadows.** In dark mode, higher-elevation surfaces should be lighter (`#141414` → `#1c1c1c` → `#262626`), not darker with shadows. +* **Shadows still work** but must be much darker (`rgba(0,0,0,0.5)`) and more diffused. Light mode shadows are cosmetic; dark mode shadows create depth. +* **Images and media:** Apply a subtle `brightness(0.9)` filter to images in dark mode to prevent eye-searing bright photos. +* **Accent colors may need adjustment.** A saturated blue that works on white may feel neon on black. Slightly lighten or desaturate accents for dark mode. + +## 12. SEO & META ARCHITECTURE +Premium design means nothing if search engines cannot index it. These rules ensure discoverability: + +### Mandatory Meta Tags +```tsx +// app/layout.tsx (Next.js App Router) +export const metadata: Metadata = { + title: { default: 'Brand Name', template: '%s | Brand Name' }, + description: 'Concise, keyword-rich description under 160 characters.', + openGraph: { + title: 'Brand Name', + description: 'Same or variant of meta description.', + url: 'https://example.com', + siteName: 'Brand Name', + images: [{ url: '/og-image.png', width: 1200, height: 630, alt: 'Brand preview' }], + locale: 'en_US', + type: 'website', + }, + twitter: { + card: 'summary_large_image', + title: 'Brand Name', + description: 'Same description.', + images: ['/og-image.png'], + }, + robots: { index: true, follow: true }, + alternates: { canonical: 'https://example.com' }, +}; +``` + +### Semantic Structure +* **One `<h1>` per page.** Never skip heading levels (h1 → h3). Use proper hierarchy: h1 → h2 → h3. +* **Structured Data (JSON-LD):** Add schema markup for Organization, Product, FAQ, BreadcrumbList as appropriate. Place in `<script type="application/ld+json">` in the `<head>`. +* **Sitemap & Robots:** Generate `sitemap.xml` and `robots.txt`. In Next.js, export from `app/sitemap.ts` and `app/robots.ts`. + +### Performance-SEO Intersection +* **Server-render critical content.** Text inside the hero, navigation links, and primary CTA must be in the initial HTML — not loaded via client-side JavaScript. Use React Server Components for all static content. +* **No content behind interactions.** If your FAQ answers are hidden in accordions, search engines may not index them. Use `<details>` elements or render content visibly for crawlers. +* **Canonical URLs** on every page to prevent duplicate content issues. +* **Alt text on all meaningful images.** Be descriptive, not generic. "`AI dashboard showing real-time analytics`" not "`image`". + +## 13. CODE EXAMPLES (Before → After) + +### Example 1: Generic Card → Premium Double-Bezel Card +```tsx +import { motion } from 'framer-motion'; + +// BEFORE — Generic AI slop +<div className="bg-white rounded-lg shadow-md p-6 border border-gray-200"> + <h3 className="text-xl font-bold text-gray-900">Feature Title</h3> + <p className="text-gray-600 mt-2">Description of the feature goes here.</p> +</div> + +// AFTER — Premium Double-Bezel with motion +<motion.div + className="rounded-[2rem] bg-zinc-100/50 dark:bg-white/[0.03] p-1.5 ring-1 ring-black/[0.03] dark:ring-white/[0.06]" + whileHover={{ y: -2 }} + transition={{ type: 'spring', stiffness: 300, damping: 25 }} +> + <div className="rounded-[calc(2rem-0.375rem)] bg-white dark:bg-zinc-900 p-8 shadow-[inset_0_1px_1px_rgba(255,255,255,0.1)]"> + <span className="inline-block rounded-full bg-emerald-50 dark:bg-emerald-950/30 px-3 py-1 text-[10px] uppercase tracking-[0.2em] font-medium text-emerald-600 dark:text-emerald-400 mb-4"> + Core + </span> + <h3 className="text-xl font-semibold tracking-tight text-zinc-900 dark:text-zinc-100"> + Feature title + </h3> + <p className="text-zinc-500 dark:text-zinc-400 mt-2 leading-relaxed max-w-[50ch]"> + A concise description that says exactly what it does without filler words. + </p> + </div> +</motion.div> +``` + +### Example 2: Generic Button → Magnetic CTA with Nested Icon +```tsx +import { motion } from 'framer-motion'; +import { ArrowUpRight } from '@phosphor-icons/react'; + +// BEFORE — Default button +<button className="bg-blue-500 text-white px-4 py-2 rounded-md hover:bg-blue-600"> + Get Started → +</button> + +// AFTER — Premium pill with nested icon + spring physics +<motion.button + className="group relative inline-flex items-center gap-3 rounded-full bg-zinc-900 dark:bg-white px-6 py-3 text-sm font-medium text-white dark:text-zinc-900 transition-all duration-300 ease-[cubic-bezier(0.32,0.72,0,1)]" + whileHover={{ scale: 1.02 }} + whileTap={{ scale: 0.98 }} +> + <span>Get started</span> + <span className="flex h-7 w-7 items-center justify-center rounded-full bg-white/10 dark:bg-black/10 transition-transform duration-300 group-hover:translate-x-0.5 group-hover:-translate-y-px group-hover:scale-110"> + <ArrowUpRight className="h-3.5 w-3.5" weight="bold" /> + </span> +</motion.button> +``` + +### Example 3: Static Section → Scroll-Animated Entry with Reduced Motion +```tsx +// BEFORE — Static mount, no animation +<section className="py-12"> + <h2>Our Features</h2> + <div className="grid grid-cols-3 gap-4">...</div> +</section> + +// AFTER — Staggered entry respecting reduced motion +'use client'; +import { motion, useReducedMotion } from 'framer-motion'; + +type Feature = { + id: string | number; + title: string; + description: string; +}; + +function FeaturesSection({ features }: { features: Feature[] }) { + const shouldReduce = useReducedMotion(); + + const container = { + hidden: {}, + show: { transition: { staggerChildren: shouldReduce ? 0 : 0.08 } }, + }; + + const item = shouldReduce + ? {} + : { + hidden: { opacity: 0, y: 24 }, + show: { + opacity: 1, y: 0, + transition: { type: 'spring', stiffness: 100, damping: 20 }, + }, + }; + + return ( + <section className="py-32 px-4"> + <h2 className="text-4xl md:text-6xl font-semibold tracking-tighter text-zinc-900 dark:text-zinc-100 mb-16"> + What we build + </h2> + <motion.div + className="grid grid-cols-1 md:grid-cols-2 gap-6 max-w-7xl mx-auto" + variants={container} + initial="hidden" + whileInView="show" + viewport={{ once: true, margin: '-100px' }} + > + {features.map((f) => ( + <motion.div key={f.id} variants={item}> + {/* Double-Bezel card here */} + </motion.div> + ))} + </motion.div> + </section> + ); +} +``` + +### Example 4: Theme Toggle with System Detection +```tsx +'use client'; +import { useEffect, useState } from 'react'; +import { Monitor, Moon, Sun } from '@phosphor-icons/react'; + +type Theme = 'light' | 'dark' | 'system'; + +export function ThemeToggle() { + const [theme, setTheme] = useState<Theme>('system'); + + useEffect(() => { + const stored = localStorage.getItem('theme') as Theme | null; + if (stored) setTheme(stored); + }, []); + + useEffect(() => { + const root = document.documentElement; + const applyTheme = (resolvedTheme: 'light' | 'dark') => { + root.classList.toggle('dark', resolvedTheme === 'dark'); + }; + + if (theme === 'system') { + const mq = matchMedia('(prefers-color-scheme: dark)'); + applyTheme(mq.matches ? 'dark' : 'light'); + const handler = (e: MediaQueryListEvent) => applyTheme(e.matches ? 'dark' : 'light'); + mq.addEventListener('change', handler); + localStorage.removeItem('theme'); + return () => mq.removeEventListener('change', handler); + } else { + applyTheme(theme); + localStorage.setItem('theme', theme); + } + }, [theme]); + + const options = [ + { value: 'light' as Theme, icon: Sun }, + { value: 'system' as Theme, icon: Monitor }, + { value: 'dark' as Theme, icon: Moon }, + ]; + + return ( + <div className="flex items-center gap-1 rounded-full bg-zinc-100 dark:bg-zinc-800 p-1"> + {options.map(({ value, icon: Icon }) => ( + <button + key={value} + onClick={() => setTheme(value)} + className={`rounded-full p-2 transition-colors ${ + theme === value + ? 'bg-white dark:bg-zinc-700 shadow-sm' + : 'hover:bg-zinc-200 dark:hover:bg-zinc-700' + }`} + aria-label={`Switch to ${value} mode`} + aria-pressed={theme === value} + > + <Icon className="h-4 w-4 text-zinc-600 dark:text-zinc-300" weight="bold" /> + </button> + ))} + </div> + ); +} +``` + +## 14. FINAL PRE-FLIGHT CHECK Evaluate your code against this matrix before outputting. This is the **last** filter you apply to your logic. - [ ] Is global state used appropriately to avoid deep prop-drilling rather than arbitrarily? - [ ] Is mobile layout collapse (`w-full`, `px-4`, `max-w-7xl mx-auto`) guaranteed for high-variance designs? @@ -224,3 +543,11 @@ Evaluate your code against this matrix before outputting. This is the **last** f - [ ] Are empty, loading, and error states provided? - [ ] Are cards omitted in favor of spacing where possible? - [ ] Did you strictly isolate CPU-heavy perpetual animations in their own Client Components? +- [ ] Do ALL animations respect `prefers-reduced-motion`? (Section 10) +- [ ] Does every interactive element have visible focus indicators and ARIA labels? (Section 10) +- [ ] Is color contrast at least 4.5:1 for normal text and 3:1 for large text? (Section 10) +- [ ] Are all images using responsive formats (WebP/AVIF) with explicit dimensions? (Section 5) +- [ ] Is LCP < 2.5s with hero image preloaded? (Section 5) +- [ ] Does the page have proper meta tags, OG image, canonical URL, and JSON-LD? (Section 12) +- [ ] Does dark mode use elevated surfaces (lighter bg) instead of inverted shadows? (Section 11) +- [ ] Is semantic HTML used (`<nav>`, `<main>`, `<section>`) instead of div soup? (Section 10)