{
  "$schema": "https://shadcn-vue.com/schema/registry-item.json",
  "name": "knowledge-base-hub",
  "title": "Knowledge Base Hub",
  "type": "registry:block",
  "files": [
    {
      "path": "packages/registry-vue/blocks/knowledge-base-hub/KnowledgeBaseHub.vue",
      "content": "<script setup lang=\"ts\">\nimport type { Component, HTMLAttributes } from 'vue'\nimport { computed, ref } from 'vue'\nimport {\n  ArrowRight,\n  ArrowUpRight,\n  Blocks,\n  Clock,\n  Code,\n  CreditCard,\n  Eye,\n  HelpCircle,\n  MessageSquare,\n  Rocket,\n  Search,\n  Shield,\n  Users,\n} from 'lucide-vue-next'\nimport { cn } from '@/lib/utils'\nimport { Badge } from '@/components/ui/badge'\nimport { Button } from '@/components/ui/button'\nimport { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '@/components/ui/card'\nimport KnowledgeHeroSearch from './KnowledgeHeroSearch.vue'\n\ninterface Category {\n  id: string\n  title: string\n  description: string\n  articlesCount: number\n  icon: Component\n  featuredTopics: string[]\n}\n\ninterface Article {\n  id: string\n  title: string\n  description: string\n  category: string\n  readTime: string\n  viewCount: string\n}\n\nconst props = defineProps<{\n  class?: HTMLAttributes['class']\n}>()\n\nconst searchQuery = ref('')\n\nconst categories: Category[] = [\n  {\n    id: 'getting-started',\n    title: 'Getting Started',\n    icon: Rocket,\n    articlesCount: 14,\n    description: 'Quick start guides, installation walkthroughs, and core architecture concepts.',\n    featuredTopics: ['Quickstart Guide', 'Project Setup', 'First Deployment'],\n  },\n  {\n    id: 'account-billing',\n    title: 'Account & Billing',\n    icon: CreditCard,\n    articlesCount: 22,\n    description: 'Subscription plans, payment methods, invoice management, and seat licensing.',\n    featuredTopics: ['Upgrade Plan', 'Payment Methods', 'Invoices'],\n  },\n  {\n    id: 'api-sdks',\n    title: 'API & Developer SDKs',\n    icon: Code,\n    articlesCount: 35,\n    description: 'REST & GraphQL endpoints, SDK reference libraries, auth tokens, and rate limits.',\n    featuredTopics: ['Authentication', 'Rate Limits', 'SDK Libraries'],\n  },\n  {\n    id: 'security-compliance',\n    title: 'Security & Compliance',\n    icon: Shield,\n    articlesCount: 18,\n    description: 'SOC 2 certification, SSO/SAML configuration, audit logs, and data encryption.',\n    featuredTopics: ['SAML SSO', 'Audit Logs', 'Data Encryption'],\n  },\n  {\n    id: 'integrations-webhooks',\n    title: 'Integrations & Webhooks',\n    icon: Blocks,\n    articlesCount: 28,\n    description: 'Connecting third-party apps, custom webhooks, payload schemas, and event retries.',\n    featuredTopics: ['Webhooks Setup', 'Slack App', 'Retry Policies'],\n  },\n  {\n    id: 'troubleshooting-faq',\n    title: 'Troubleshooting & FAQ',\n    icon: HelpCircle,\n    articlesCount: 40,\n    description: 'Common error codes, debugging workflows, known limits, and frequent questions.',\n    featuredTopics: ['Error Codes', 'Performance', 'Account Recovery'],\n  },\n]\n\nconst trendingArticles: Article[] = [\n  {\n    id: 'art-1',\n    title: 'Setting up SAML 2.0 Single Sign-On (SSO)',\n    description: 'Step-by-step instructions for configuring Okta, Azure AD, and Google Workspace SSO.',\n    category: 'Security',\n    readTime: '6 min read',\n    viewCount: '14.2k views',\n  },\n  {\n    id: 'art-2',\n    title: 'Migrating from v1 REST API to v2 GraphQL',\n    description: 'Breaking changes, schema transformations, and backward-compatibility guidelines.',\n    category: 'API & SDKs',\n    readTime: '8 min read',\n    viewCount: '11.8k views',\n  },\n  {\n    id: 'art-3',\n    title: 'Configuring Custom Domains & SSL Certificates',\n    description: 'DNS record configuration, automatic TLS provisioning, and apex domain routing.',\n    category: 'Getting Started',\n    readTime: '4 min read',\n    viewCount: '9.5k views',\n  },\n  {\n    id: 'art-4',\n    title: 'Webhook Signatures & Replay Attack Prevention',\n    description: 'Verify HMAC-SHA256 signatures and implement idempotency keys for event handling.',\n    category: 'Integrations',\n    readTime: '5 min read',\n    viewCount: '8.9k views',\n  },\n  {\n    id: 'art-5',\n    title: 'Managing Team Roles & Granular Permissions',\n    description: 'Assigning RBAC policies, custom permission sets, and project-level scopes.',\n    category: 'Account',\n    readTime: '5 min read',\n    viewCount: '7.4k views',\n  },\n  {\n    id: 'art-6',\n    title: 'Debugging 429 Rate Limit Errors & Backoff Strategies',\n    description: 'Understanding quota tiers, exponential backoff algorithms, and jitter implementations.',\n    category: 'Troubleshooting',\n    readTime: '7 min read',\n    viewCount: '12.1k views',\n  },\n]\n\nconst filteredCategories = computed(() => {\n  const q = searchQuery.value.trim().toLowerCase()\n  if (!q) return categories\n  return categories.filter(\n    (c) =>\n      c.title.toLowerCase().includes(q) ||\n      c.description.toLowerCase().includes(q) ||\n      c.featuredTopics.some((t) => t.toLowerCase().includes(q)),\n  )\n})\n\nconst filteredArticles = computed(() => {\n  const q = searchQuery.value.trim().toLowerCase()\n  if (!q) return trendingArticles\n  return trendingArticles.filter(\n    (a) =>\n      a.title.toLowerCase().includes(q) ||\n      a.description.toLowerCase().includes(q) ||\n      a.category.toLowerCase().includes(q),\n  )\n})\n</script>\n\n<template>\n  <div data-slot=\"knowledge-base-hub\" :class=\"cn('w-full space-y-12 py-6', props.class)\">\n    <!-- Hero Header -->\n    <KnowledgeHeroSearch :search-query=\"searchQuery\" @update:search-query=\"searchQuery = $event\" />\n\n    <!-- Empty Search State -->\n    <div\n      v-if=\"filteredCategories.length === 0 && filteredArticles.length === 0\"\n      class=\"border-border bg-card/40 rounded-xl border border-dashed p-10 text-center\"\n    >\n      <div class=\"bg-muted text-muted-foreground mx-auto flex size-12 items-center justify-center rounded-full\">\n        <Search class=\"size-6\" aria-hidden=\"true\" />\n      </div>\n      <h3 class=\"mt-4 text-base font-semibold\">No matching articles found</h3>\n      <p class=\"text-muted-foreground mt-1 text-sm\">\n        No guides or categories matched &ldquo;{{ searchQuery }}&rdquo;. Try searching for another topic.\n      </p>\n      <Button aria-label=\"Clear search\" variant=\"outline\" size=\"sm\" class=\"mt-4\" @click=\"searchQuery = ''\">\n        Reset search\n      </Button>\n    </div>\n\n    <!-- Category Cards Grid -->\n    <section v-if=\"filteredCategories.length > 0\" class=\"space-y-4\">\n      <div class=\"flex items-center justify-between\">\n        <h2 class=\"text-xl font-semibold tracking-tight sm:text-2xl\">Browse by Category</h2>\n        <span class=\"text-muted-foreground text-xs tabular-nums\"> {{ filteredCategories.length }} categories </span>\n      </div>\n\n      <div class=\"grid gap-5 sm:grid-cols-2 lg:grid-cols-3\">\n        <Card\n          v-for=\"category in filteredCategories\"\n          :key=\"category.id\"\n          class=\"group/card hover:border-ring/50 relative flex flex-col justify-between overflow-hidden transition-colors duration-200 hover:shadow-sm\"\n        >\n          <CardHeader class=\"pb-3\">\n            <div class=\"flex items-start justify-between gap-3\">\n              <div class=\"bg-primary/10 text-primary flex size-11 items-center justify-center rounded-lg\">\n                <component :is=\"category.icon\" class=\"size-5\" aria-hidden=\"true\" />\n              </div>\n              <Badge variant=\"secondary\" class=\"text-xs font-normal\"> {{ category.articlesCount }} articles </Badge>\n            </div>\n            <CardTitle class=\"mt-3 text-lg font-semibold tracking-tight\">\n              {{ category.title }}\n            </CardTitle>\n            <CardDescription class=\"text-muted-foreground text-sm leading-relaxed\">\n              {{ category.description }}\n            </CardDescription>\n          </CardHeader>\n          <CardContent class=\"pt-0\">\n            <div class=\"border-border flex flex-wrap gap-1.5 border-t pt-3\">\n              <span\n                v-for=\"topic in category.featuredTopics\"\n                :key=\"topic\"\n                class=\"bg-muted/60 text-muted-foreground rounded-md px-2 py-0.5 text-xs font-medium\"\n              >\n                {{ topic }}\n              </span>\n            </div>\n          </CardContent>\n          <CardFooter class=\"border-border bg-muted/20 flex items-center justify-between border-t py-3\">\n            <a\n              href=\"#\"\n              class=\"text-primary group-hover/card:text-primary/80 focus-visible:ring-ring flex min-h-6 items-center gap-1 text-xs font-medium transition-colors focus-visible:ring-2 focus-visible:outline-none\"\n            >\n              <span>Explore category</span>\n              <ArrowRight class=\"size-3.5 transition-transform duration-200 group-hover/card:translate-x-1\" />\n            </a>\n          </CardFooter>\n        </Card>\n      </div>\n    </section>\n\n    <!-- Popular & Trending Articles Section -->\n    <section v-if=\"filteredArticles.length > 0\" class=\"space-y-4\">\n      <div class=\"flex flex-col justify-between gap-2 sm:flex-row sm:items-end\">\n        <div>\n          <h2 class=\"text-xl font-semibold tracking-tight sm:text-2xl\">Popular & Trending Articles</h2>\n          <p class=\"text-muted-foreground mt-1 text-sm\">\n            Frequently read guides and developer documentation this week.\n          </p>\n        </div>\n        <a\n          href=\"#\"\n          class=\"text-primary hover:text-primary/80 inline-flex min-h-6 items-center gap-1 text-xs font-medium transition-colors\"\n        >\n          <span>View all documentation</span>\n          <ArrowRight class=\"size-3.5\" aria-hidden=\"true\" />\n        </a>\n      </div>\n\n      <div class=\"grid gap-4 md:grid-cols-2\">\n        <Card\n          v-for=\"article in filteredArticles\"\n          :key=\"article.id\"\n          class=\"group/article hover:border-ring/50 relative flex flex-col justify-between p-5 transition-colors duration-200 hover:shadow-sm\"\n        >\n          <div class=\"space-y-2.5\">\n            <div class=\"flex items-center justify-between gap-2\">\n              <Badge variant=\"outline\" class=\"text-xs font-medium\">\n                {{ article.category }}\n              </Badge>\n              <div class=\"text-muted-foreground flex items-center gap-3 text-xs\">\n                <span class=\"inline-flex items-center gap-1\">\n                  <Clock class=\"size-3.5\" aria-hidden=\"true\" />\n                  {{ article.readTime }}\n                </span>\n                <span class=\"inline-flex items-center gap-1\">\n                  <Eye class=\"size-3.5\" aria-hidden=\"true\" />\n                  {{ article.viewCount }}\n                </span>\n              </div>\n            </div>\n\n            <div>\n              <a\n                href=\"#\"\n                class=\"text-foreground group-hover/article:text-primary focus-visible:ring-ring flex items-start justify-between gap-2 text-base font-semibold tracking-tight transition-colors focus-visible:ring-2 focus-visible:outline-none\"\n              >\n                <span>{{ article.title }}</span>\n                <ArrowUpRight\n                  class=\"text-muted-foreground group-hover/article:text-primary size-4 shrink-0 transition-transform duration-200 group-hover/article:translate-x-0.5 group-hover/article:-translate-y-0.5\"\n                  aria-hidden=\"true\"\n                />\n              </a>\n              <p class=\"text-muted-foreground mt-1 line-clamp-2 text-sm leading-relaxed\">\n                {{ article.description }}\n              </p>\n            </div>\n          </div>\n        </Card>\n      </div>\n    </section>\n\n    <!-- Community & Live Support Footer Banner -->\n    <Card class=\"border-border bg-card/60 overflow-hidden shadow-xs\">\n      <CardContent\n        class=\"flex flex-col items-center justify-between gap-6 p-8 text-center sm:p-10 md:flex-row md:text-left\"\n      >\n        <div class=\"max-w-xl space-y-2\">\n          <h3 class=\"text-xl font-semibold tracking-tight sm:text-2xl\">\n            Can&apos;t find what you&apos;re looking for?\n          </h3>\n          <p class=\"text-muted-foreground text-sm leading-relaxed\">\n            Our support engineers are available 24/7 to help resolve technical issues, or join our Discord community to\n            connect with other developers.\n          </p>\n        </div>\n        <div class=\"flex shrink-0 flex-wrap items-center justify-center gap-3\">\n          <Button class=\"gap-2\">\n            <MessageSquare class=\"size-4\" aria-hidden=\"true\" />\n            <span>Contact Support</span>\n          </Button>\n          <Button variant=\"outline\" class=\"gap-2\">\n            <Users class=\"size-4\" aria-hidden=\"true\" />\n            <span>Join Discord Community</span>\n          </Button>\n        </div>\n      </CardContent>\n    </Card>\n  </div>\n</template>\n",
      "type": "registry:block",
      "target": "~/app/components/blocks/KnowledgeBaseHub.vue"
    },
    {
      "path": "packages/registry-vue/blocks/knowledge-base-hub/KnowledgeHeroSearch.vue",
      "content": "<script setup lang=\"ts\">\nimport { BookOpen, Search, X } from 'lucide-vue-next'\nimport { cn } from '@/lib/utils'\nimport { Badge } from '@/components/ui/badge'\nimport { Input } from '@/components/ui/input'\n\nconst props = defineProps<{\n  searchQuery: string\n}>()\n\nconst emit = defineEmits<{ 'update:searchQuery': [value: string] }>()\n\nconst quickTopics = ['Authentication', 'Billing', 'Webhooks', 'Custom Domains']\n\nfunction selectTopic(topic: string) {\n  if (props.searchQuery === topic) {\n    emit('update:searchQuery', '')\n  } else {\n    emit('update:searchQuery', topic)\n  }\n}\n\nfunction onInput(value: string | number) {\n  emit('update:searchQuery', String(value))\n}\n</script>\n\n<template>\n  <section class=\"mx-auto max-w-3xl space-y-6 text-center\">\n    <div class=\"space-y-3\">\n      <Badge variant=\"secondary\" class=\"gap-1.5 px-3 py-1 font-medium\">\n        <BookOpen class=\"text-primary size-3.5\" aria-hidden=\"true\" />\n        Help Center & Documentation\n      </Badge>\n      <h1 class=\"text-3xl font-bold tracking-tight sm:text-4xl lg:text-5xl\">How can we help you today?</h1>\n      <p class=\"text-muted-foreground mx-auto max-w-xl text-base sm:text-lg\">\n        Search our knowledge base for guides, API references, troubleshooting tips, and common workflows.\n      </p>\n    </div>\n\n    <div class=\"relative mx-auto max-w-2xl\">\n      <Search\n        aria-hidden=\"true\"\n        class=\"text-muted-foreground pointer-events-none absolute top-1/2 left-4 size-5 -translate-y-1/2\"\n      />\n      <Input\n        :model-value=\"searchQuery\"\n        type=\"search\"\n        placeholder=\"Search for answers, guides, and error codes...\"\n        class=\"bg-card h-12 rounded-xl pr-14 pl-11 text-base shadow-xs\"\n        @update:model-value=\"onInput\"\n      />\n      <div class=\"pointer-events-none absolute top-1/2 right-3 -translate-y-1/2\">\n        <kbd\n          class=\"bg-muted text-muted-foreground border-border hidden h-6 items-center rounded border px-2 font-mono text-xs select-none sm:inline-flex\"\n        >\n          ⌘K\n        </kbd>\n      </div>\n    </div>\n\n    <div class=\"flex flex-wrap items-center justify-center gap-2\">\n      <span class=\"text-muted-foreground text-xs font-medium\">Quick topics:</span>\n      <button\n        v-for=\"topic in quickTopics\"\n        :key=\"topic\"\n        type=\"button\"\n        :class=\"\n          cn(\n            'focus-visible:ring-ring inline-flex items-center rounded-full border px-3 py-1 text-xs font-medium transition-colors focus-visible:ring-2 focus-visible:outline-none',\n            searchQuery === topic\n              ? 'bg-primary text-primary-foreground border-primary'\n              : 'bg-muted/50 text-muted-foreground hover:bg-muted hover:text-foreground border-transparent',\n          )\n        \"\n        @click=\"selectTopic(topic)\"\n      >\n        {{ topic }}\n      </button>\n      <button\n        aria-label=\"Clear search\"\n        v-if=\"searchQuery\"\n        type=\"button\"\n        class=\"text-muted-foreground hover:text-foreground inline-flex items-center gap-1 px-1.5 py-1 text-xs font-medium transition-colors\"\n        @click=\"emit('update:searchQuery', '')\"\n      >\n        <X class=\"size-3\" aria-hidden=\"true\" />\n        Clear search\n      </button>\n    </div>\n  </section>\n</template>\n",
      "type": "registry:block",
      "target": "~/app/components/blocks/KnowledgeHeroSearch.vue"
    }
  ],
  "dependencies": [
    "lucide-vue-next"
  ],
  "devDependencies": [],
  "registryDependencies": [
    "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"
  ],
  "description": "Self-serve help center and customer documentation hub with hero search, quick topic pills, category cards grid, trending articles, and community support banner.",
  "categories": [
    "media",
    "support",
    "marketing"
  ]
}