{
  "$schema": "https://shadcn-vue.com/schema/registry-item.json",
  "name": "seo-audit-checklist",
  "title": "Seo Audit Checklist",
  "type": "registry:block",
  "files": [
    {
      "path": "packages/registry-vue/blocks/seo-audit-checklist/SeoAuditChecklist.vue",
      "content": "<script setup lang=\"ts\">\nimport { ref, computed } from 'vue'\nimport type { HTMLAttributes } from 'vue'\nimport {\n  AlertCircle,\n  AlertTriangle,\n  Check,\n  CheckCircle2,\n  Code2,\n  Copy,\n  Eye,\n  FileDown,\n  FileText,\n  Globe,\n  Heading1,\n  Info,\n  Lock,\n  Monitor,\n  RefreshCw,\n  Search,\n  Share2,\n  ShieldCheck,\n  Smartphone,\n  Zap,\n} from 'lucide-vue-next'\nimport { cn } from '@/lib/utils'\nimport { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from '@/components/ui/accordion'\nimport { Badge } from '@/components/ui/badge'\nimport { Button } from '@/components/ui/button'\nimport { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'\nimport { Input } from '@/components/ui/input'\nimport { Progress } from '@/components/ui/progress'\nimport { Separator } from '@/components/ui/separator'\n\nexport type CheckStatus = 'pass' | 'warning' | 'fail' | 'info'\n\nexport interface SeoCheckItem {\n  id: string\n  title: string\n  description: string\n  status: CheckStatus\n  value?: string\n  recommendation?: string\n  tag?: string\n}\n\nexport interface SeoCategory {\n  id: string\n  name: string\n  icon: 'meta' | 'headings' | 'opengraph' | 'technical'\n  score: number\n  checks: SeoCheckItem[]\n}\n\nexport interface CoreVitalMetric {\n  name: string\n  label: string\n  value: string\n  status: 'good' | 'needs-improvement' | 'poor'\n  target: string\n}\n\nexport interface SeoAuditChecklistProps {\n  url?: string\n  score?: number\n  lastAudited?: string\n  titleTag?: string\n  metaDescription?: string\n  h1Tag?: string\n  ogImageUrl?: string\n  categories?: SeoCategory[]\n  vitals?: CoreVitalMetric[]\n  class?: HTMLAttributes['class']\n}\n\nconst defaultVitals: CoreVitalMetric[] = [\n  { name: 'LCP', label: 'Largest Contentful Paint', value: '1.2s', status: 'good', target: '≤ 2.5s' },\n  { name: 'FID', label: 'First Input Delay', value: '12ms', status: 'good', target: '≤ 100ms' },\n  { name: 'CLS', label: 'Cumulative Layout Shift', value: '0.01', status: 'good', target: '≤ 0.1' },\n]\n\nconst defaultCategories: SeoCategory[] = [\n  {\n    id: 'meta-tags',\n    name: 'Title & Meta Description',\n    icon: 'meta',\n    score: 100,\n    checks: [\n      {\n        id: 'title-length',\n        title: 'Title Tag Length & Structure',\n        description: 'Page title is 58 characters (optimal range: 50–60 characters). Fully visible in 98% of SERPs.',\n        status: 'pass',\n        value: 'UIPKGE — Dual-Framework UI Registry for Vue & React',\n        tag: '58 / 60 chars',\n      },\n      {\n        id: 'meta-desc',\n        title: 'Meta Description Length',\n        description:\n          'Meta description is 152 characters (optimal range: 140–160 characters). Rich keyword density without truncation.',\n        status: 'pass',\n        value:\n          'Explore high-quality, copy-paste Vue and React UI components and blocks built with Tailwind CSS v4, Reka UI, and Lucide icons.',\n        tag: '152 / 160 chars',\n      },\n      {\n        id: 'canonical-url',\n        title: 'Canonical URL Tag',\n        description: 'Self-referencing canonical URL tag prevents duplicate content indexing across query variants.',\n        status: 'pass',\n        value: '<link rel=\"canonical\" href=\"https://uipkge.dev/vue/components\" />',\n        tag: 'Present',\n      },\n      {\n        id: 'meta-robots',\n        title: 'Meta Robots Directives',\n        description: 'Directives instruct crawlers to index the document and follow embedded hyperlinks.',\n        status: 'pass',\n        value: 'index, follow, max-image-preview:large, max-snippet:-1',\n        tag: 'Index, Follow',\n      },\n    ],\n  },\n  {\n    id: 'headings',\n    name: 'Heading Hierarchy & Structure',\n    icon: 'headings',\n    score: 100,\n    checks: [\n      {\n        id: 'h1-presence',\n        title: 'Single Primary H1 Tag',\n        description: 'Exactly 1 H1 tag detected containing target search terms and establishing clear topic authority.',\n        status: 'pass',\n        value: '<h1>UIPKGE Component & Block Registry</h1>',\n        tag: '1 H1 Tag',\n      },\n      {\n        id: 'h2-distribution',\n        title: 'H2 Section Organization',\n        description: '6 H2 tags logically divide major categories (Primitives, Blocks, Forms, Marketing, Feedback).',\n        status: 'pass',\n        value: '6 H2 tags · 0 skipped levels',\n        tag: '6 H2 Tags',\n      },\n      {\n        id: 'h3-nesting',\n        title: 'H3 Subsection Hierarchy',\n        description: '12 H3 tags cleanly nested under parent H2 sections without skipping hierarchical levels.',\n        status: 'pass',\n        value: '12 H3 tags · Valid tree hierarchy',\n        tag: '12 H3 Tags',\n      },\n      {\n        id: 'content-depth',\n        title: 'Content Word Count & Substance',\n        description: '1,840 words detected with strong semantic depth for component discovery.',\n        status: 'pass',\n        value: '1,840 words · 4.2 min read',\n        tag: 'Substantial',\n      },\n    ],\n  },\n  {\n    id: 'opengraph',\n    name: 'OpenGraph & Social Share Cards',\n    icon: 'opengraph',\n    score: 100,\n    checks: [\n      {\n        id: 'og-title-desc',\n        title: 'OpenGraph Title & Description',\n        description: 'Social graph tags are present and optimized for display across Twitter/X, LinkedIn, and Discord.',\n        status: 'pass',\n        value: 'og:title, og:description, og:type, og:url configured',\n        tag: 'Configured',\n      },\n      {\n        id: 'og-image',\n        title: 'OpenGraph Social Banner Image',\n        description:\n          '1200 × 630px high-resolution banner image detected with crisp aspect ratio (1.91:1) and fast CDN delivery.',\n        status: 'pass',\n        value: 'https://uipkge.dev/og/components.png (1200x630 · 84 KB)',\n        tag: '1200x630 px',\n      },\n      {\n        id: 'twitter-card',\n        title: 'Twitter / X Card Format',\n        description: 'Card format explicitly set to summary_large_image for maximal feed visibility.',\n        status: 'pass',\n        value: 'twitter:card = summary_large_image',\n        tag: 'Large Image',\n      },\n    ],\n  },\n  {\n    id: 'technical',\n    name: 'Performance, Images & Technical SEO',\n    icon: 'technical',\n    score: 85,\n    checks: [\n      {\n        id: 'image-alt-tags',\n        title: 'Image Alt Attributes',\n        description:\n          'All 24 embedded images contain meaningful, non-empty alt text attributes for accessibility and image search.',\n        status: 'pass',\n        value: '24 / 24 images with valid alt text (100%)',\n        tag: '24 / 24 Pass',\n      },\n      {\n        id: 'broken-links',\n        title: 'Crawlable Hyperlinks & 404 Errors',\n        description: 'Crawled 142 internal and external links. 0 broken links or redirect loops detected.',\n        status: 'pass',\n        value: '142 links verified · 0 errors',\n        tag: '0 Broken',\n      },\n      {\n        id: 'ssl-security',\n        title: 'SSL / HTTPS & Security Headers',\n        description: 'Valid TLS 1.3 certificate with HSTS header enabled and automatic HTTP-to-HTTPS redirect.',\n        status: 'pass',\n        value: 'TLS 1.3 · HSTS Active · HTTP/2 Supported',\n        tag: 'Secure',\n      },\n      {\n        id: 'schema-markup',\n        title: 'Schema.org Structured Data',\n        description:\n          'No SoftwareApplication or Product JSON-LD schema detected. Structured data enables rich Google SERP snippet features.',\n        status: 'warning',\n        value: 'Missing schema.org/SoftwareApplication microdata',\n        recommendation:\n          'Add JSON-LD script tag with SoftwareApplication schema to qualify for rich snippet search results.',\n        tag: 'Missing Schema',\n      },\n    ],\n  },\n]\n\nconst props = withDefaults(defineProps<SeoAuditChecklistProps>(), {\n  url: 'https://uipkge.dev/vue/components',\n  score: 94,\n  lastAudited: 'Audit completed in 640ms · Cached 2m ago',\n  titleTag: 'UIPKGE — Dual-Framework UI Registry for Vue & React',\n  metaDescription:\n    'Explore high-quality, copy-paste Vue and React UI components and blocks built with Tailwind CSS v4, Reka UI, and Lucide icons. Unbundled registry with full source code ownership.',\n  h1Tag: 'UIPKGE Component & Block Registry',\n  ogImageUrl: 'https://images.unsplash.com/photo-1618005182384-a83a8bd57fbe?w=1200&auto=format&fit=crop&q=80',\n})\n\nconst activeCategories = computed(() => props.categories ?? defaultCategories)\nconst activeVitals = computed(() => props.vitals ?? defaultVitals)\n\nconst currentUrl = ref(props.url)\nconst isAuditing = ref(false)\nconst copiedSchema = ref(false)\nconst copiedUrl = ref(false)\nconst reportDownloaded = ref(false)\nconst previewDevice = ref<'desktop' | 'mobile'>('desktop')\nconst activeStatusFilter = ref<'all' | 'pass' | 'warning'>('all')\n\nconst allChecks = computed(() => activeCategories.value.flatMap((cat) => cat.checks))\nconst passCount = computed(() => allChecks.value.filter((c) => c.status === 'pass').length)\nconst warningCount = computed(() => allChecks.value.filter((c) => c.status === 'warning').length)\nconst totalCount = computed(() => allChecks.value.length)\n\nconst filteredCategories = computed(() => {\n  if (activeStatusFilter.value === 'all') return activeCategories.value\n  return activeCategories.value\n    .map((cat) => ({\n      ...cat,\n      checks: cat.checks.filter((check) => check.status === activeStatusFilter.value),\n    }))\n    .filter((cat) => cat.checks.length > 0)\n})\n\nfunction handleReaudit() {\n  isAuditing.value = true\n  setTimeout(() => {\n    isAuditing.value = false\n  }, 500)\n}\n\nfunction handleCopySchema() {\n  copiedSchema.value = true\n  setTimeout(() => {\n    copiedSchema.value = false\n  }, 1800)\n}\n\nfunction handleCopyUrl() {\n  copiedUrl.value = true\n  setTimeout(() => {\n    copiedUrl.value = false\n  }, 1800)\n}\n\nfunction handleDownloadReport() {\n  reportDownloaded.value = true\n  setTimeout(() => {\n    reportDownloaded.value = false\n  }, 2000)\n}\n</script>\n\n<template>\n  <div :class=\"cn('w-full space-y-6', props.class)\" data-slot=\"seo-audit-checklist\">\n    <!-- Header & Audit Control Center -->\n    <Card class=\"border-border bg-card shadow-xs\">\n      <CardContent class=\"p-5 sm:p-6\">\n        <div class=\"flex flex-col gap-5 lg:flex-row lg:items-center lg:justify-between\">\n          <!-- Left: Target URL & Score -->\n          <div class=\"space-y-3\">\n            <div class=\"flex flex-wrap items-center gap-3\">\n              <div\n                class=\"border-success/30 bg-success/10 text-success flex items-center gap-1.5 rounded-full border px-3 py-1 text-xs font-semibold\"\n              >\n                <span class=\"relative flex size-2\">\n                  <span class=\"bg-success absolute inline-flex h-full w-full rounded-full opacity-75\" />\n                  <span class=\"bg-success relative inline-flex size-2 rounded-full\" />\n                </span>\n                <span class=\"font-mono tabular-nums\">{{ props.score }} / 100</span>\n                <span>·</span>\n                <span>Healthy Score</span>\n              </div>\n              <Badge wrap variant=\"outline\" class=\"gap-1 text-xs font-normal\">\n                <Globe class=\"text-muted-foreground size-3\" />\n                HTTP 200 OK\n              </Badge>\n              <Badge wrap variant=\"outline\" class=\"gap-1 text-xs font-normal\">\n                <ShieldCheck class=\"text-success size-3\" />\n                Indexable\n              </Badge>\n            </div>\n\n            <div>\n              <h1 class=\"text-foreground text-lg font-bold tracking-tight sm:text-xl\">\n                On-Page SEO Analyzer & Snippet Simulator\n              </h1>\n              <p class=\"text-muted-foreground text-xs\">\n                {{ props.lastAudited }}\n              </p>\n            </div>\n          </div>\n\n          <!-- Right: Action Buttons -->\n          <div class=\"flex flex-wrap items-center gap-2.5 sm:self-start lg:self-center\">\n            <Button\n              variant=\"outline\"\n              size=\"sm\"\n              class=\"h-9 gap-1.5 text-xs shadow-xs\"\n              :disabled=\"isAuditing\"\n              @click=\"handleReaudit\"\n            >\n              <RefreshCw :class=\"['size-3.5', isAuditing ? 'animate-spin' : '']\" />\n              <span>Re-audit URL</span>\n            </Button>\n\n            <Button\n              aria-label=\"Download attachment\"\n              size=\"sm\"\n              class=\"h-9 gap-1.5 text-xs font-medium shadow-xs\"\n              @click=\"handleDownloadReport\"\n            >\n              <FileDown v-if=\"!reportDownloaded\" class=\"size-3.5\" />\n              <Check v-else class=\"text-success size-3.5\" />\n              <span>{{ reportDownloaded ? 'Report Exported!' : 'Download SEO Report' }}</span>\n            </Button>\n          </div>\n        </div>\n\n        <Separator class=\"my-4\" />\n\n        <!-- URL Input Strip -->\n        <div class=\"flex flex-col gap-2 sm:flex-row sm:items-center\">\n          <div class=\"relative flex-1\">\n            <div class=\"text-muted-foreground pointer-events-none absolute inset-y-0 left-0 flex items-center pl-3\">\n              <Search class=\"size-4\" />\n            </div>\n            <Input\n              v-model=\"currentUrl\"\n              type=\"url\"\n              placeholder=\"https://yourdomain.com/path\"\n              class=\"h-9 w-full rounded-md pr-24 pl-9 font-mono text-xs shadow-xs\"\n              @keydown.enter=\"handleReaudit\"\n            />\n            <button\n              type=\"button\"\n              class=\"text-muted-foreground hover:text-foreground absolute inset-y-0 right-0 flex min-h-6 items-center pr-3 text-xs transition-colors\"\n              @click=\"handleCopyUrl\"\n            >\n              <Check v-if=\"copiedUrl\" class=\"text-success size-3.5\" />\n              <Copy v-else class=\"size-3.5\" />\n              <span class=\"ml-1 text-xs\">{{ copiedUrl ? 'Copied' : 'Copy' }}</span>\n            </button>\n          </div>\n          <Button\n            size=\"sm\"\n            variant=\"secondary\"\n            class=\"h-9 shrink-0 px-4 text-xs font-medium\"\n            :disabled=\"isAuditing\"\n            @click=\"handleReaudit\"\n          >\n            <Search class=\"text-primary mr-1.5 size-3.5\" />\n            Analyze Page\n          </Button>\n        </div>\n      </CardContent>\n    </Card>\n\n    <!-- 4 Core SEO Pillar Metric Cards -->\n    <div class=\"grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4\">\n      <!-- Pillar 1: Meta Tags & Snippet -->\n      <Card class=\"border-border bg-card shadow-xs\">\n        <CardHeader class=\"flex flex-row items-center justify-between space-y-0 pb-2\">\n          <CardTitle class=\"text-muted-foreground text-xs font-medium\">Meta Tags & Snippet</CardTitle>\n          <div\n            class=\"border-border/60 bg-muted/60 text-muted-foreground flex size-7 items-center justify-center rounded-md border\"\n          >\n            <FileText class=\"text-success size-3.5\" />\n          </div>\n        </CardHeader>\n        <CardContent class=\"space-y-2\">\n          <div class=\"flex flex-wrap items-baseline justify-between gap-x-2 gap-y-0.5\">\n            <div class=\"text-foreground text-xl font-bold tracking-tight sm:text-2xl\">100% Pass</div>\n            <Badge wrap variant=\"success\" class=\"text-xs font-medium\">Optimal</Badge>\n          </div>\n          <div class=\"space-y-1.5\">\n            <Progress :model-value=\"100\" class=\"bg-success/20 [&>div]:bg-success h-1.5 w-full\" />\n            <p class=\"text-muted-foreground text-xs\">Title & description optimized</p>\n          </div>\n          <div\n            class=\"border-border/50 text-muted-foreground flex items-center justify-between border-t pt-2 font-mono text-xs\"\n          >\n            <span>58 chars title</span>\n            <span>·</span>\n            <span>152 chars desc</span>\n          </div>\n        </CardContent>\n      </Card>\n\n      <!-- Pillar 2: Core Web Vitals -->\n      <Card class=\"border-border bg-card shadow-xs\">\n        <CardHeader class=\"flex flex-row items-center justify-between space-y-0 pb-2\">\n          <CardTitle class=\"text-muted-foreground text-xs font-medium\">Core Web Vitals</CardTitle>\n          <div\n            class=\"border-border/60 bg-muted/60 text-muted-foreground flex size-7 items-center justify-center rounded-md border\"\n          >\n            <Zap class=\"text-success size-3.5\" />\n          </div>\n        </CardHeader>\n        <CardContent class=\"space-y-2\">\n          <div class=\"flex flex-wrap items-baseline justify-between gap-x-2 gap-y-0.5\">\n            <div class=\"text-foreground text-xl font-bold tracking-tight sm:text-2xl\">Good</div>\n            <Badge wrap variant=\"success\" class=\"text-xs font-medium\">98/100</Badge>\n          </div>\n          <div class=\"space-y-1.5\">\n            <Progress :model-value=\"98\" class=\"bg-success/20 [&>div]:bg-success h-1.5 w-full\" />\n            <p class=\"text-muted-foreground text-xs\">LCP 1.2s · FID 12ms · CLS 0.01</p>\n          </div>\n          <div\n            class=\"border-border/50 text-muted-foreground flex items-center justify-between border-t pt-2 font-mono text-xs\"\n          >\n            <span>Chrome UX Report</span>\n            <span>·</span>\n            <span class=\"text-success\">Passed</span>\n          </div>\n        </CardContent>\n      </Card>\n\n      <!-- Pillar 3: Mobile Usability -->\n      <Card class=\"border-border bg-card shadow-xs\">\n        <CardHeader class=\"flex flex-row items-center justify-between space-y-0 pb-2\">\n          <CardTitle class=\"text-muted-foreground text-xs font-medium\">Mobile Usability</CardTitle>\n          <div\n            class=\"border-border/60 bg-muted/60 text-muted-foreground flex size-7 items-center justify-center rounded-md border\"\n          >\n            <Smartphone class=\"text-success size-3.5\" />\n          </div>\n        </CardHeader>\n        <CardContent class=\"space-y-2\">\n          <div class=\"flex flex-wrap items-baseline justify-between gap-x-2 gap-y-0.5\">\n            <div class=\"text-foreground text-xl font-bold tracking-tight sm:text-2xl\">100% Pass</div>\n            <Badge wrap variant=\"success\" class=\"text-xs font-medium\">Valid</Badge>\n          </div>\n          <div class=\"space-y-1.5\">\n            <Progress :model-value=\"100\" class=\"bg-success/20 [&>div]:bg-success h-1.5 w-full\" />\n            <p class=\"text-muted-foreground text-xs\">Touch targets & viewport valid</p>\n          </div>\n          <div\n            class=\"border-border/50 text-muted-foreground flex items-center justify-between border-t pt-2 font-mono text-xs\"\n          >\n            <span>48px tap targets</span>\n            <span>·</span>\n            <span>0 horizontal scroll</span>\n          </div>\n        </CardContent>\n      </Card>\n\n      <!-- Pillar 4: Indexability & Crawl -->\n      <Card class=\"border-border bg-card shadow-xs\">\n        <CardHeader class=\"flex flex-row items-center justify-between space-y-0 pb-2\">\n          <CardTitle class=\"text-muted-foreground text-xs font-medium\">Indexability & Crawl</CardTitle>\n          <div\n            class=\"border-border/60 bg-muted/60 text-muted-foreground flex size-7 items-center justify-center rounded-md border\"\n          >\n            <ShieldCheck class=\"text-success size-3.5\" />\n          </div>\n        </CardHeader>\n        <CardContent class=\"space-y-2\">\n          <div class=\"flex flex-wrap items-baseline justify-between gap-x-2 gap-y-0.5\">\n            <div class=\"text-foreground text-xl font-bold tracking-tight sm:text-2xl\">Valid</div>\n            <Badge wrap variant=\"success\" class=\"text-xs font-medium\">Indexed</Badge>\n          </div>\n          <div class=\"space-y-1.5\">\n            <Progress :model-value=\"95\" class=\"bg-success/20 [&>div]:bg-success h-1.5 w-full\" />\n            <p class=\"text-muted-foreground text-xs\">Canonical URL present & sitemap verified</p>\n          </div>\n          <div\n            class=\"border-border/50 text-muted-foreground flex items-center justify-between border-t pt-2 font-mono text-xs\"\n          >\n            <span>robots.txt allowed</span>\n            <span>·</span>\n            <span>sitemap.xml</span>\n          </div>\n        </CardContent>\n      </Card>\n    </div>\n\n    <!-- Google Search Result Snippet Preview Simulator -->\n    <Card class=\"border-border bg-card shadow-xs\">\n      <CardHeader class=\"flex flex-col gap-3 pb-4 sm:flex-row sm:items-center sm:justify-between\">\n        <div>\n          <div class=\"flex items-center gap-2\">\n            <CardTitle class=\"text-base font-semibold\">Google Search Result Snippet Preview</CardTitle>\n            <Badge wrap variant=\"outline\" class=\"gap-1 text-xs font-normal\">\n              <Eye class=\"text-primary size-3\" />\n              Live SERP Simulator\n            </Badge>\n          </div>\n          <CardDescription class=\"text-xs\">\n            Simulate how your meta tags, title, and URL render in Google SERPs on desktop vs. mobile.\n          </CardDescription>\n        </div>\n\n        <!-- Desktop / Mobile View Switcher -->\n        <div class=\"border-border bg-muted/50 flex items-center rounded-lg border p-0.5\">\n          <button\n            type=\"button\"\n            :class=\"[\n              'flex min-h-6 items-center gap-1.5 rounded-md px-3 py-1 text-xs font-medium transition-colors',\n              previewDevice === 'desktop'\n                ? 'bg-background text-foreground shadow-xs'\n                : 'text-muted-foreground hover:text-foreground',\n            ]\"\n            @click=\"previewDevice = 'desktop'\"\n          >\n            <Monitor class=\"size-3.5\" />\n            <span>Desktop</span>\n          </button>\n          <button\n            type=\"button\"\n            :class=\"[\n              'flex min-h-6 items-center gap-1.5 rounded-md px-3 py-1 text-xs font-medium transition-colors',\n              previewDevice === 'mobile'\n                ? 'bg-background text-foreground shadow-xs'\n                : 'text-muted-foreground hover:text-foreground',\n            ]\"\n            @click=\"previewDevice = 'mobile'\"\n          >\n            <Smartphone class=\"size-3.5\" />\n            <span>Mobile</span>\n          </button>\n        </div>\n      </CardHeader>\n\n      <CardContent class=\"space-y-4\">\n        <!-- Mock Google SERP Result Box -->\n        <div\n          :class=\"[\n            'border-border/80 bg-background mx-auto rounded-xl border p-4 shadow-xs transition-colors duration-200 sm:p-5',\n            previewDevice === 'mobile' ? 'border-border max-w-md' : 'w-full',\n          ]\"\n        >\n          <!-- Google Result Header / Breadcrumb -->\n          <div class=\"flex items-center gap-2.5 pb-1.5\">\n            <div\n              class=\"border-border bg-muted text-foreground flex size-7 shrink-0 items-center justify-center rounded-full border text-xs font-bold\"\n            >\n              ⚡\n            </div>\n            <div class=\"min-w-0 flex-1\">\n              <div class=\"text-foreground flex items-center gap-1.5 text-xs\">\n                <span class=\"font-medium\">uipkge.dev</span>\n                <span class=\"text-muted-foreground\">›</span>\n                <span class=\"text-muted-foreground truncate\">vue › components</span>\n              </div>\n              <p class=\"text-muted-foreground truncate font-mono text-xs\">{{ props.url }}</p>\n            </div>\n          </div>\n\n          <!-- Google SERP Title -->\n          <div class=\"space-y-1 pt-1\">\n            <a\n              href=\"#\"\n              class=\"text-info text-info block text-base leading-snug font-medium hover:underline sm:text-lg\"\n              @click.prevent\n            >\n              {{ props.titleTag }}\n            </a>\n\n            <!-- Google Snippet Description with highlighted keywords -->\n            <p class=\"text-muted-foreground text-xs leading-relaxed sm:text-sm\">\n              <span class=\"text-muted-foreground/90 font-medium\">Aug 20, 2026 — </span>\n              Explore high-quality, copy-paste\n              <strong class=\"text-foreground font-semibold\">Vue</strong> and\n              <strong class=\"text-foreground font-semibold\">React</strong>\n              <strong class=\"text-foreground font-semibold\">UI components</strong> and blocks built with\n              <strong class=\"text-foreground font-semibold\">Tailwind CSS v4</strong>, Reka UI, and Lucide icons.\n              Unbundled registry with full source code ownership.\n            </p>\n          </div>\n\n          <!-- Google Rich Snippet Badges -->\n          <div class=\"border-border/40 mt-3 flex flex-wrap items-center gap-2 border-t pt-2.5\">\n            <Badge wrap variant=\"secondary\" class=\"text-xs font-normal\"> ★ 4.9 · 1.4k GitHub Stars </Badge>\n            <Badge wrap variant=\"outline\" class=\"text-xs font-normal\"> Free & Open Source </Badge>\n            <Badge wrap variant=\"outline\" class=\"text-xs font-normal\"> Vue 3.5 + React 19 </Badge>\n          </div>\n        </div>\n\n        <!-- Snippet Metrics Character / Pixel Budget Strip -->\n        <div class=\"border-border/80 bg-muted/30 grid grid-cols-1 gap-3 rounded-lg border p-3 sm:grid-cols-3\">\n          <div class=\"min-w-0 space-y-1\">\n            <div class=\"flex items-center justify-between text-xs\">\n              <span class=\"text-muted-foreground\">Title Tag Budget:</span>\n              <span class=\"text-foreground font-mono font-semibold tabular-nums\">58 / 60 chars</span>\n            </div>\n            <Progress :model-value=\"(58 / 60) * 100\" class=\"bg-success/20 [&>div]:bg-success h-1.5 w-full\" />\n            <p class=\"text-success text-xs\">Optimal (485px / 600px max SERP width)</p>\n          </div>\n\n          <div class=\"min-w-0 space-y-1\">\n            <div class=\"flex items-center justify-between text-xs\">\n              <span class=\"text-muted-foreground\">Meta Description:</span>\n              <span class=\"text-foreground font-mono font-semibold tabular-nums\">152 / 160 chars</span>\n            </div>\n            <Progress :model-value=\"(152 / 160) * 100\" class=\"bg-success/20 [&>div]:bg-success h-1.5 w-full\" />\n            <p class=\"text-success text-xs\">Optimal (890px / 960px max SERP width)</p>\n          </div>\n\n          <div class=\"flex flex-col justify-between space-y-1\">\n            <div class=\"flex items-center justify-between text-xs\">\n              <span class=\"text-muted-foreground\">Truncation Risk:</span>\n              <Badge wrap variant=\"success\" class=\"px-1.5 py-0 text-xs\">0% Truncation</Badge>\n            </div>\n            <p class=\"text-muted-foreground text-xs\">Fully visible on both desktop & mobile Google viewports.</p>\n          </div>\n        </div>\n      </CardContent>\n    </Card>\n\n    <!-- Actionable Recommendation Callout Banner -->\n    <Card class=\"border-warning/30 bg-warning/10 shadow-xs\">\n      <CardContent class=\"p-5\">\n        <div class=\"flex flex-col gap-4 lg:flex-row lg:items-start lg:justify-between\">\n          <div class=\"flex items-start gap-3\">\n            <div\n              class=\"border-warning/30 bg-warning/20 text-warning mt-0.5 flex size-8 shrink-0 items-center justify-center rounded-lg border\"\n            >\n              <AlertTriangle class=\"size-4\" />\n            </div>\n            <div class=\"space-y-1.5\">\n              <div class=\"flex flex-wrap items-center gap-2\">\n                <h3 class=\"text-foreground text-sm font-semibold\">\n                  Actionable Recommendation: Add Schema.org JSON-LD Structured Data\n                </h3>\n                <Badge wrap variant=\"warning\" class=\"text-xs\">High Impact</Badge>\n              </div>\n              <p class=\"text-muted-foreground text-xs leading-relaxed\">\n                Adding\n                <code\n                  class=\"bg-background/80 text-foreground border-border rounded border px-1 py-0.5 font-mono text-xs\"\n                  >SoftwareApplication</code\n                >\n                or\n                <code\n                  class=\"bg-background/80 text-foreground border-border rounded border px-1 py-0.5 font-mono text-xs\"\n                  >TechArticle</code\n                >\n                structured data enables Google Rich Snippets, rating stars, and knowledge graph carousels.\n              </p>\n\n              <!-- Inline Code Preview -->\n              <div\n                class=\"border-border/80 bg-background/90 text-foreground mt-2 rounded-md border p-3 font-mono text-xs\"\n              >\n                <div class=\"text-muted-foreground flex items-center justify-between pb-1.5\">\n                  <span class=\"text-xs\">Recommended JSON-LD Block</span>\n                  <button\n                    type=\"button\"\n                    class=\"text-muted-foreground hover:text-foreground flex min-h-6 items-center gap-1 text-xs transition-colors\"\n                    @click=\"handleCopySchema\"\n                  >\n                    <Check v-if=\"copiedSchema\" class=\"text-success size-3\" />\n                    <Copy v-else class=\"size-3\" />\n                    <span>{{ copiedSchema ? 'Copied' : 'Copy JSON-LD' }}</span>\n                  </button>\n                </div>\n                <pre class=\"text-muted-foreground overflow-x-auto text-xs leading-snug\"><code>{\n  \"@context\": \"https://schema.org\",\n  \"@type\": \"SoftwareApplication\",\n  \"name\": \"UIPKGE\",\n  \"applicationCategory\": \"DeveloperApplication\",\n  \"operatingSystem\": \"Web\",\n  \"offers\": { \"@type\": \"Offer\", \"price\": \"0\", \"priceCurrency\": \"USD\" }\n}</code></pre>\n              </div>\n            </div>\n          </div>\n\n          <Button variant=\"outline\" size=\"sm\" class=\"shrink-0 gap-1.5 text-xs shadow-xs\" @click=\"handleCopySchema\">\n            <Code2 class=\"size-3.5\" />\n            <span>Copy Schema Snippet</span>\n          </Button>\n        </div>\n      </CardContent>\n    </Card>\n\n    <!-- Audit Checklist Grouped Accordion Section -->\n    <div class=\"space-y-4\">\n      <div class=\"flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between\">\n        <div>\n          <h2 class=\"text-foreground text-sm font-semibold tracking-tight\">Detailed On-Page Audit Checklist</h2>\n          <p class=\"text-muted-foreground text-xs\">\n            Complete verification of on-page meta tags, heading semantics, social cards, and technical crawlability.\n          </p>\n        </div>\n\n        <!-- Filter Tabs -->\n        <div class=\"flex items-center gap-1.5\">\n          <Button\n            variant=\"ghost\"\n            size=\"sm\"\n            :class=\"[\n              'h-8 px-2.5 text-xs',\n              activeStatusFilter === 'all' ? 'bg-muted text-foreground font-medium' : 'text-muted-foreground',\n            ]\"\n            @click=\"activeStatusFilter = 'all'\"\n          >\n            All Checks ({{ totalCount }})\n          </Button>\n          <Button\n            variant=\"ghost\"\n            size=\"sm\"\n            :class=\"[\n              'h-8 px-2.5 text-xs',\n              activeStatusFilter === 'pass' ? 'bg-muted text-success font-medium' : 'text-muted-foreground',\n            ]\"\n            @click=\"activeStatusFilter = 'pass'\"\n          >\n            Passed ({{ passCount }})\n          </Button>\n          <Button\n            variant=\"ghost\"\n            size=\"sm\"\n            :class=\"[\n              'h-8 px-2.5 text-xs',\n              activeStatusFilter === 'warning' ? 'bg-muted text-warning font-medium' : 'text-muted-foreground',\n            ]\"\n            @click=\"activeStatusFilter = 'warning'\"\n          >\n            Warnings ({{ warningCount }})\n          </Button>\n        </div>\n      </div>\n\n      <!-- Accordion List -->\n      <Accordion type=\"multiple\" :default-value=\"['meta-tags', 'headings', 'opengraph', 'technical']\" class=\"space-y-3\">\n        <AccordionItem\n          v-for=\"category in filteredCategories\"\n          :key=\"category.id\"\n          :value=\"category.id\"\n          class=\"border-border bg-card overflow-hidden rounded-lg border shadow-xs\"\n        >\n          <AccordionTrigger class=\"px-5 py-4 hover:no-underline\">\n            <div class=\"flex w-full flex-wrap items-center justify-between gap-3 pr-2 text-left\">\n              <div class=\"flex items-center gap-3\">\n                <div\n                  class=\"border-border/60 bg-muted/60 text-muted-foreground flex size-8 shrink-0 items-center justify-center rounded-md border\"\n                >\n                  <FileText v-if=\"category.icon === 'meta'\" class=\"size-4\" />\n                  <Heading1 v-else-if=\"category.icon === 'headings'\" class=\"size-4\" />\n                  <Share2 v-else-if=\"category.icon === 'opengraph'\" class=\"size-4\" />\n                  <Lock v-else class=\"size-4\" />\n                </div>\n                <div>\n                  <span class=\"text-foreground text-sm font-semibold\">{{ category.name }}</span>\n                  <p class=\"text-muted-foreground text-xs\">\n                    {{ category.checks.filter((c) => c.status === 'pass').length }} of\n                    {{ category.checks.length }} tests passing\n                  </p>\n                </div>\n              </div>\n\n              <div class=\"flex items-center gap-2.5\">\n                <Badge\n                  :variant=\"category.score === 100 ? 'success' : 'warning'\"\n                  class=\"text-xs font-semibold whitespace-normal tabular-nums\"\n                >\n                  {{ category.score }}% Score\n                </Badge>\n              </div>\n            </div>\n          </AccordionTrigger>\n\n          <AccordionContent class=\"px-5 pt-0 pb-5\">\n            <div class=\"divide-border/60 border-border/60 divide-y border-t\">\n              <div v-for=\"check in category.checks\" :key=\"check.id\" class=\"space-y-2 py-3.5 first:pt-4 last:pb-1\">\n                <div class=\"flex flex-col gap-1.5 sm:flex-row sm:items-start sm:justify-between sm:gap-3\">\n                  <div class=\"min-w-0 space-y-1\">\n                    <div class=\"flex items-center gap-2\">\n                      <CheckCircle2 v-if=\"check.status === 'pass'\" class=\"text-success size-4 shrink-0\" />\n                      <AlertTriangle v-else-if=\"check.status === 'warning'\" class=\"text-warning size-4 shrink-0\" />\n                      <AlertCircle v-else class=\"text-destructive size-4 shrink-0\" />\n                      <h4 class=\"text-foreground text-xs font-semibold sm:text-sm\">{{ check.title }}</h4>\n                    </div>\n                    <p class=\"text-muted-foreground pl-6 text-xs leading-relaxed\">{{ check.description }}</p>\n                  </div>\n\n                  <div class=\"flex flex-wrap items-center gap-2 pl-6 sm:pl-0\">\n                    <Badge wrap v-if=\"check.tag\" variant=\"outline\" class=\"font-mono text-xs font-normal\">\n                      {{ check.tag }}\n                    </Badge>\n                    <Badge\n                      :variant=\"\n                        check.status === 'pass' ? 'success' : check.status === 'warning' ? 'warning' : 'destructive'\n                      \"\n                      class=\"text-xs font-medium whitespace-normal capitalize\"\n                    >\n                      {{ check.status }}\n                    </Badge>\n                  </div>\n                </div>\n\n                <!-- Code / Value Inspector Box -->\n                <div\n                  v-if=\"check.value\"\n                  class=\"border-border/70 bg-muted/40 text-foreground ml-6 rounded-md border px-3 py-2 font-mono text-xs\"\n                >\n                  <span class=\"text-xs break-all\">{{ check.value }}</span>\n                </div>\n\n                <!-- Recommendation Callout -->\n                <div\n                  v-if=\"check.recommendation\"\n                  class=\"border-warning/30 bg-warning/10 text-warning ml-6 flex items-start gap-2 rounded-md border p-2.5 text-xs\"\n                >\n                  <Info class=\"text-warning size-4 shrink-0\" />\n                  <p class=\"text-xs leading-relaxed\">{{ check.recommendation }}</p>\n                </div>\n              </div>\n            </div>\n          </AccordionContent>\n        </AccordionItem>\n      </Accordion>\n    </div>\n  </div>\n</template>\n",
      "type": "registry:block",
      "target": "~/app/components/blocks/SeoAuditChecklist.vue"
    }
  ],
  "dependencies": [
    "lucide-vue-next"
  ],
  "devDependencies": [],
  "registryDependencies": [
    "https://uipkge.dev/r/vue/accordion.json",
    "https://uipkge.dev/r/vue/badge.json",
    "https://uipkge.dev/r/vue/button.json",
    "https://uipkge.dev/r/vue/card.json",
    "https://uipkge.dev/r/vue/input.json",
    "https://uipkge.dev/r/vue/progress.json",
    "https://uipkge.dev/r/vue/separator.json"
  ],
  "description": "Ahrefs and SEMrush style on-page SEO analyzer, meta tag auditor, Google SERP snippet preview simulator, heading hierarchy validator, and Core Web Vitals checklist.",
  "categories": [
    "marketing",
    "dashboard"
  ]
}