@xexr/blog-platform 1.0.11 → 1.0.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/lib/utils.ts","../src/components/ui/button.tsx","../src/components/ui/pagination.tsx","../src/components/Pagination.tsx","../src/lib/urls.ts","../src/lib/structured-data.ts","../src/lib/article-ui.ts","../src/components/NewsletterSignup.tsx","../src/app/blog/page.tsx","../src/components/ui/badge.tsx","../src/components/ui/card.tsx","../src/components/ArticleTopActions.tsx","../src/components/ExpandableArticleImage.tsx","../src/components/ArticleReadingProgress.tsx","../src/components/ui/separator.tsx","../src/lib/mdx.ts","../src/app/blog/%5Bslug%5D/page.tsx","../src/app/blog/authors/%5Bslug%5D/page.tsx","../src/lib/database.ts","../src/lib/authors.ts","../src/lib/topics.ts","../src/components/TopicArchivePages.tsx","../src/components/AuthorPages.tsx","../src/lib/auth.ts","../src/lib/ratelimit.ts","../src/lib/init.ts","../src/lib/storage/drizzle.ts","../src/lib/seo.ts","../src/lib/metadata.ts","../src/lib/sitemap.ts","../package.json","../src/lib/version.ts","../src/lib/security-headers.ts","../src/lib/cors.ts","../src/app/api/blog/publish/route.ts","../src/app/api/blog/unpublish/route.ts","../src/app/api/blog/version/route.ts","../src/app/api/blog/slugs/%5Bslug%5D/route.ts","../src/index.ts"],"names":["cn","inputs","twMerge","clsx","buttonVariants","cva","Button","className","variant","size","asChild","props","jsx","Slot","Pagination","PaginationContent","PaginationItem","PaginationLink","isActive","PaginationPrevious","jsxs","ChevronLeftIcon","PaginationNext","ChevronRightIcon","PaginationEllipsis","MoreHorizontalIcon","currentPage","totalPages","baseUrl","maxVisiblePages","showPrevNext","showFirstLast","getVisiblePages","half","start","end","pages","_","i","getPageUrl","page","hasPrevious","hasNext","Fragment","ChevronsLeft","ChevronsRight","usePagination","searchParams","itemsPerPage","pageParam","pageString","offset","totalItems","generatePaginationMetadata","siteUrl","canonicalUrl","prevUrl","nextUrl","normalizeBlogBasePath","basePath","trimmed","buildBlogPath","slug","normalizedBasePath","cleanSlug","buildAuthorPath","authorSlug","getPathPrefixFromBlogUrl","blogUrl","parsed","generateArticleStructuredData","article","options","customDomain","pathPrefix","language","isAccessibleForFree","includeOptionalProperties","domain","authorSchema","generateAuthorStructuredData","publisherSchema","generateOrganizationStructuredData","timeRequired","schema","topic","author","sameAs","url","authorUrl","site","generateWebSiteStructuredData","includeSearchAction","generateBreadcrumbStructuredData","breadcrumbs","crumb","index","generateCompleteArticleStructuredData","schemas","generateBlogHomeStructuredData","featuredArticles","articleSchemas","validateStructuredData","errors","blogSchema","structuredDataToJsonLd","createStructuredDataScript","extractKeywordsFromArticle","keywords","keyword","tone","StructuredDataError","message","code","details","safeGenerateArticleStructuredData","validation","error","DEFAULT_THEME","getBlogThemeStyle","theme","formatArticleDateMeta","publishedAt","updatedAt","publishedDate","updatedDate","format","formatDistanceToNow","extractTableOfContents","markdown","items","inFence","line","match","text","stripMarkdownInline","slugifyHeading","formatTableOfContentsSummary","count","getTocItemState","itemId","activeItemId","value","NEWSLETTER_SUCCESS_MESSAGE","NewsletterSignup","siteId","settings","sourceSurface","sourceArticleSlug","sourceUrl","previewMode","setMessage","useState","setError","hasSubmitted","setHasSubmitted","isSubmitting","setIsSubmitting","subscriptionKey","getSubscriptionStorageKey","hasStoredSubscribed","useSyncExternalStore","subscribeToStoredSubscription","hasStoredSubscription","hasSubscribed","handleSubmit","event","formData","honeypot","getFormString","response","getOptionalFormString","resolveSourceUrl","result","successMessage","getNewsletterResponseMessage","storeSubscription","Check","ArrowUpRight","key","cookie","callback","BlogHomePage","articles","siteName","siteTagline","includeStructuredData","pagination","newsletter","newsletterPreviewMode","newsletterSettings","newsletterSiteId","ArticlePreview","structuredDataProps","formatReadingTime","seconds","articleUrl","formattedDate","readingTime","imageUrl","Link","Image","AuthorLink","AuthorAvatar","sizeClass","initials","getAuthorInitials","name","part","generateBlogHomeMetadata","siteDescription","baseTitle","title","description","badgeVariants","Badge","Card","CardHeader","CardTitle","CardDescription","CardContent","CardFooter","resolveShareUrl","currentHref","copyArticleLink","clipboard","fallbackDocument","textarea","shareArticle","navigatorLike","ArticleTopActions","copied","setCopied","React","sharing","setSharing","resolvedUrl","timeout","handleCopy","handleShare","buttonClassName","iconClassName","Copy","Share2","ExpandableArticleImage","alt","src","previewId","hashImageSrc","hash","ArticleReadingProgress","contentId","showProgress","ArticleTableOfContents","getReadingProgressScript","list","item","itemState","Separator","Bt","orientation","decorative","ref","articleMdxOptions","remarkToc","remarkGfm","rehypeUnwrapStandaloneImages","rehypeSlug","tree","unwrapStandaloneImages","node","child","isStandaloneImageParagraph","isMeaningfulNode","meaningfulChildren","isImageLikeNode","formatCreditUrl","FeaturedImageCredit","creditText","creditUrl","label","ArticlePage","navigation","postArticleCta","relatedArticles","showShareLinks","dateMeta","tocItems","hasFeaturedImageMeta","ArrowLeft","MDXRemote","AuthorSocialLinks","PostArticleCta","ArticleShareLinks","RelatedArticles","ArticleCardImage","links","getAuthorSocialLinks","link","Globe","FaXTwitter","FaLinkedinIn","FaGithub","Mail","cta","encodedTitle","encodedUrl","generateArticleMetadata","ogImage","AuthorPage","backUrl","totalArticleCount","AuthorArticlePreview","publishedRelativeLabel","generateAuthorPageMetadata","InMemoryStorage","idempotencyKey","existingResult","limit","sortBy","order","allArticles","a","b","aValue","bValue","warnAboutEphemeralStorage","globalRef","getGlobalStorage","storage","getStorage","setStorage","getAuthorsFromArticles","authorsBySlug","mergeAuthorProfile","getAuthorArchive","authorArticles","preferredAuthor","loadAuthorArchive","current","next","getArticlePrimaryTopic","topics","getAllTopics","topicsBySlug","getTopicArchive","topicSlug","matchingArticles","candidate","BlogTopicsIndexPage","articleTopic","BlogTopicArchivePage","archive","TopicArticleCard","publishedAgo","BlogAuthorsIndexPage","authors","extractTokenFromHeader","request","authHeader","bearerMatch","tokenMatch","ApiKeyAuth","apiKeys","token","EnvAuth","envVarName","apiKeysEnv","NoAuth","UninitializedAuth","_token","getDefaultAuthConfig","setAuthConfig","config","getAuthConfig","initEnvAuth","authenticateRequest","createAuthErrorResponse","authResult","customMessages","requireAuth","auth","shouldSkipAuth","skipAuth","getRateLimiter","setRateLimiter","instance","configureRateLimit","redisUrl","redisToken","requestsPerMinute","keyPrefix","analytics","redis","Redis","limiter","Ratelimit","autoConfigureRateLimit","checkRateLimit","identifier","createRateLimitErrorResponse","rateLimitResult","resetMinutes","enforceRateLimit","getRateLimitHeaders","initBlogPlatform","rateLimit","autoRateLimit","initBlogPlatformOnce","initBlogPlatformDev","initBlogPlatformProd","apiKeysEnvVar","envVar","bpArticles","sqliteTable","integer","table","uniqueIndex","bpOperations","toRow","fromRow","row","extractTopics","extractMeta","metaJson","DrizzleStorage","db","existing","eq","bySlug","existingRow","conflict","and","success","rows","orderColumn","orderBy","desc","totalRow","sql","total","notFound","now","expiresAt","getDrizzleAdapterSql","normalizeDomain","forceHttps","normalized","normalizeSlug","clean","generateCanonicalUrl","removeTrailingSlash","normalizedDomain","normalizedSlug","cleanPrefix","generateCanonicalUrlFromSlug","isValidCanonicalUrl","getBaseUrl","updateArticleCanonicalUrl","generateSiteMetadata","pageInfo","path","meta","openGraph","twitter","generateTwitterCardMetadata","overrides","image","metadataToHtml","metadata","elements","escapeHtml","tag","attrs","htmlEscapes","char","validateMetadata","warnings","generateBlogSitemapEntries","includeAuthorPages","includePaginationPages","articlesPerPage","maxEntries","changeFrequency","priority","entries","getLatestModificationDate","latestAuthorMod","generateSitemap","generatedAt","potentialEntries","willTruncate","sitemapToXml","sitemapData","xmlHeader","urlsetOpen","urlsetClose","urlEntries","entry","escapeXml","generateSitemapIndex","sitemaps","_baseUrl","indexOpen","indexClose","sitemapEntries","sitemap","validateSitemap","isValidISODate","urlCounts","latest","articleDate","createBlogSitemapRoute","xmlEntries","xml","createDynamicBlogSitemap","xmlEscapes","dateString","date","isoString","normalizedInput","package_default","parseVersion","version","parts","major","minor","patch","getBlogPlatformVersion","versionComponents","parseVersionHeader","headerValue","versionInfo","checkVersionCompatibility","version1","version2","DEFAULT_SECURITY_CONFIG","getSecurityConfig","envCSPDisabled","envFrameOptions","envHSTSDisabled","buildCSPHeader","directives","directive","buildPermissionsPolicyHeader","feature","allowlist","getSecurityHeaders","securityConfig","headers","cspDirectives","isHTTPS","hstsValue","permissionsDirectives","getAPISecurityHeaders","DEFAULT_CORS_CONFIG","getCorsConfig","envOrigins","allowWildcard","allowCredentials","origin","isOriginAllowed","getCorsHeaders","getPreflightHeaders","allowedMethods","allowedHeaders","STANDARD_ALLOWED_HEADERS","createCorsResponse","data","status","corsConfig","corsHeaders","securityHeaders","responseHeaders","NextResponse","handleCorsOptions","preflightHeaders","POST","authCheck","rateLimitCheck","rateLimitData","rateLimitHeaders","payload","validationErrors","validatePublishPayload","clientVersionHeader","parsedVersions","platformVersion","finalArticle","isValidSlug","statusCode","p","requiredFields","field","requiredSiteFields","validateUnpublishPayload","existingArticle","GET","errorResponse","errorVersionResponse","bloggyVersion","compatibility","params","exists","responseBody","OPTIONS","PACKAGE_VERSION"],"mappings":"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","file":"index.mjs","sourcesContent":["import { clsx, type ClassValue } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n","import * as React from \"react\"\nimport { Slot } from \"@radix-ui/react-slot\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"../../lib/utils\"\n\nconst buttonVariants = cva(\n \"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive\",\n {\n variants: {\n variant: {\n default:\n \"bg-primary text-primary-foreground shadow-xs hover:bg-primary/90\",\n destructive:\n \"bg-destructive text-white shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60\",\n outline:\n \"border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50\",\n secondary:\n \"bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80\",\n ghost:\n \"hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50\",\n link: \"text-primary underline-offset-4 hover:underline\",\n },\n size: {\n default: \"h-9 px-4 py-2 has-[>svg]:px-3\",\n sm: \"h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5\",\n lg: \"h-10 rounded-md px-6 has-[>svg]:px-4\",\n icon: \"size-9\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n }\n)\n\nfunction Button({\n className,\n variant,\n size,\n asChild = false,\n ...props\n}: React.ComponentProps<\"button\"> &\n VariantProps<typeof buttonVariants> & {\n asChild?: boolean\n }) {\n const Comp = asChild ? Slot : \"button\"\n\n return (\n <Comp\n data-slot=\"button\"\n className={cn(buttonVariants({ variant, size, className }))}\n {...props}\n />\n )\n}\n\nexport { Button, buttonVariants }\n","import * as React from \"react\"\nimport {\n ChevronLeftIcon,\n ChevronRightIcon,\n MoreHorizontalIcon,\n} from \"lucide-react\"\n\nimport { cn } from \"../../lib/utils\"\nimport { buttonVariants } from \"./button\"\n\nfunction Pagination({ className, ...props }: React.ComponentProps<\"nav\">) {\n return (\n <nav\n role=\"navigation\"\n aria-label=\"pagination\"\n data-slot=\"pagination\"\n className={cn(\"mx-auto flex w-full justify-center\", className)}\n {...props}\n />\n )\n}\n\nfunction PaginationContent({\n className,\n ...props\n}: React.ComponentProps<\"ul\">) {\n return (\n <ul\n data-slot=\"pagination-content\"\n className={cn(\"flex flex-row items-center gap-1\", className)}\n {...props}\n />\n )\n}\n\nfunction PaginationItem({ ...props }: React.ComponentProps<\"li\">) {\n return <li data-slot=\"pagination-item\" {...props} />\n}\n\ntype PaginationLinkProps = {\n isActive?: boolean\n size?: \"default\" | \"sm\" | \"lg\" | \"icon\"\n} & React.ComponentProps<\"a\">\n\nfunction PaginationLink({\n className,\n isActive,\n size = \"icon\",\n ...props\n}: PaginationLinkProps) {\n return (\n <a\n aria-current={isActive ? \"page\" : undefined}\n data-slot=\"pagination-link\"\n data-active={isActive}\n className={cn(\n buttonVariants({\n variant: isActive ? \"outline\" : \"ghost\",\n size,\n }),\n className\n )}\n {...props}\n />\n )\n}\n\nfunction PaginationPrevious({\n className,\n ...props\n}: React.ComponentProps<typeof PaginationLink>) {\n return (\n <PaginationLink\n aria-label=\"Go to previous page\"\n size=\"default\"\n className={cn(\"gap-1 px-2.5 sm:pl-2.5\", className)}\n {...props}\n >\n <ChevronLeftIcon />\n <span className=\"hidden sm:block\">Previous</span>\n </PaginationLink>\n )\n}\n\nfunction PaginationNext({\n className,\n ...props\n}: React.ComponentProps<typeof PaginationLink>) {\n return (\n <PaginationLink\n aria-label=\"Go to next page\"\n size=\"default\"\n className={cn(\"gap-1 px-2.5 sm:pr-2.5\", className)}\n {...props}\n >\n <span className=\"hidden sm:block\">Next</span>\n <ChevronRightIcon />\n </PaginationLink>\n )\n}\n\nfunction PaginationEllipsis({\n className,\n ...props\n}: React.ComponentProps<\"span\">) {\n return (\n <span\n aria-hidden\n data-slot=\"pagination-ellipsis\"\n className={cn(\"flex size-9 items-center justify-center\", className)}\n {...props}\n >\n <MoreHorizontalIcon className=\"size-4\" />\n <span className=\"sr-only\">More pages</span>\n </span>\n )\n}\n\nexport {\n Pagination,\n PaginationContent,\n PaginationLink,\n PaginationItem,\n PaginationPrevious,\n PaginationNext,\n PaginationEllipsis,\n}\n","import React from \"react\";\nimport { ChevronsLeft, ChevronsRight } from \"lucide-react\";\nimport {\n Pagination as ShadcnPagination,\n PaginationContent,\n PaginationItem,\n PaginationLink,\n PaginationNext,\n PaginationPrevious,\n PaginationEllipsis,\n} from \"./ui/pagination\";\n\nexport interface PaginationProps {\n /** Current page number (1-indexed) */\n currentPage: number;\n \n /** Total number of pages */\n totalPages: number;\n \n /** Base URL for pagination links (e.g., \"/blog\") */\n baseUrl: string;\n \n /** Additional CSS classes */\n className?: string;\n \n /** Maximum number of page links to show around current page */\n maxVisiblePages?: number;\n \n /** Show/hide previous and next buttons */\n showPrevNext?: boolean;\n \n /** Show/hide first and last page links */\n showFirstLast?: boolean;\n \n /** Custom labels for navigation */\n labels?: {\n previous?: string;\n next?: string;\n first?: string;\n last?: string;\n };\n}\n\n/**\n * Pagination component for blog articles listing.\n * \n * Provides SEO-friendly pagination with proper URL structure,\n * keyboard navigation, and accessibility features.\n */\nexport default function Pagination({\n currentPage,\n totalPages,\n baseUrl,\n className,\n maxVisiblePages = 5,\n showPrevNext = true,\n showFirstLast = true,\n}: PaginationProps) {\n // Don't render pagination if there's only one page or no pages\n if (totalPages <= 1) {\n return null;\n }\n\n // Calculate visible page range\n const getVisiblePages = () => {\n const half = Math.floor(maxVisiblePages / 2);\n let start = Math.max(1, currentPage - half);\n const end = Math.min(totalPages, start + maxVisiblePages - 1);\n \n // Adjust start if we're near the end\n if (end - start + 1 < maxVisiblePages) {\n start = Math.max(1, end - maxVisiblePages + 1);\n }\n \n return { start, end };\n };\n\n const { start, end } = getVisiblePages();\n const pages = Array.from({ length: end - start + 1 }, (_, i) => start + i);\n\n // Generate URL for a specific page\n const getPageUrl = (page: number) => {\n if (page === 1) {\n return baseUrl;\n }\n return `${baseUrl}?page=${page}`;\n };\n\n const hasPrevious = currentPage > 1;\n const hasNext = currentPage < totalPages;\n\n return (\n <ShadcnPagination className={className}>\n <PaginationContent>\n {/* First Page Link */}\n {showFirstLast && currentPage > 2 && (\n <>\n <PaginationItem>\n <PaginationLink href={getPageUrl(1)} aria-label=\"Go to first page\">\n <ChevronsLeft className=\"h-4 w-4\" />\n </PaginationLink>\n </PaginationItem>\n {start > 2 && (\n <PaginationItem>\n <PaginationEllipsis />\n </PaginationItem>\n )}\n </>\n )}\n\n {/* Previous Page Link */}\n {showPrevNext && (\n <PaginationItem>\n {hasPrevious ? (\n <PaginationPrevious href={getPageUrl(currentPage - 1)} />\n ) : (\n <span className=\"flex h-9 items-center justify-center gap-1 px-2.5 text-muted-foreground sm:pl-2.5\">\n <span className=\"hidden sm:block\">Previous</span>\n </span>\n )}\n </PaginationItem>\n )}\n\n {/* Page Number Links */}\n {pages.map((page) => (\n <PaginationItem key={page}>\n <PaginationLink \n href={getPageUrl(page)}\n isActive={page === currentPage}\n >\n {page}\n </PaginationLink>\n </PaginationItem>\n ))}\n\n {/* Next Page Link */}\n {showPrevNext && (\n <PaginationItem>\n {hasNext ? (\n <PaginationNext href={getPageUrl(currentPage + 1)} />\n ) : (\n <span className=\"flex h-9 items-center justify-center gap-1 px-2.5 text-muted-foreground sm:pr-2.5\">\n <span className=\"hidden sm:block\">Next</span>\n </span>\n )}\n </PaginationItem>\n )}\n\n {/* Last Page Link */}\n {showFirstLast && currentPage < totalPages - 1 && (\n <>\n {end < totalPages - 1 && (\n <PaginationItem>\n <PaginationEllipsis />\n </PaginationItem>\n )}\n <PaginationItem>\n <PaginationLink href={getPageUrl(totalPages)} aria-label=\"Go to last page\">\n <ChevronsRight className=\"h-4 w-4\" />\n </PaginationLink>\n </PaginationItem>\n </>\n )}\n </PaginationContent>\n\n {/* Screen Reader Info */}\n <div className=\"sr-only\" aria-live=\"polite\">\n Page {currentPage} of {totalPages}\n </div>\n </ShadcnPagination>\n );\n}\n\n\n/**\n * Hook to calculate pagination metadata from URL parameters.\n * Useful for extracting current page from Next.js searchParams.\n */\nexport function usePagination(\n searchParams: Record<string, string | string[] | undefined>,\n itemsPerPage = 10\n) {\n const pageParam = searchParams.page;\n const pageString = Array.isArray(pageParam) ? pageParam[0] : pageParam;\n const currentPage = Math.max(1, parseInt(pageString ?? \"1\", 10));\n\n const offset = (currentPage - 1) * itemsPerPage;\n\n const calculateTotalPages = (totalItems: number) => {\n return Math.ceil(totalItems / itemsPerPage);\n };\n\n return {\n currentPage,\n itemsPerPage,\n offset,\n calculateTotalPages\n };\n}\n\n/**\n * Generate pagination metadata for SEO.\n * Provides canonical URLs, next/prev relationships for search engines.\n */\nexport function generatePaginationMetadata(\n currentPage: number,\n totalPages: number,\n baseUrl: string,\n siteUrl?: string\n) {\n const canonicalUrl = siteUrl \n ? `${siteUrl}${currentPage === 1 ? baseUrl : `${baseUrl}?page=${currentPage}`}`\n : undefined;\n\n const prevUrl = currentPage > 1 \n ? siteUrl \n ? `${siteUrl}${currentPage === 2 ? baseUrl : `${baseUrl}?page=${currentPage - 1}`}`\n : undefined\n : undefined;\n\n const nextUrl = currentPage < totalPages \n ? siteUrl \n ? `${siteUrl}${baseUrl}?page=${currentPage + 1}`\n : undefined\n : undefined;\n\n return {\n alternates: {\n ...(canonicalUrl && { canonical: canonicalUrl }),\n },\n other: {\n ...(prevUrl && { prev: prevUrl }),\n ...(nextUrl && { next: nextUrl }),\n },\n };\n}","/**\n * URL helpers shared by package UI, metadata, and sitemap integrations.\n */\n\nexport function normalizeBlogBasePath(basePath = \"/blog\"): string {\n const trimmed = basePath.trim();\n if (!trimmed || trimmed === \"/\") return \"\";\n\n return trimmed.replace(/^(?!\\/)/, \"/\").replace(/\\/+$/, \"\");\n}\n\nexport function buildBlogPath(\n basePath: string | undefined,\n slug?: string,\n): string {\n const normalizedBasePath = normalizeBlogBasePath(basePath);\n const cleanSlug = slug?.replace(/^\\/+/, \"\").replace(/\\/+$/, \"\");\n\n if (!cleanSlug) {\n return normalizedBasePath || \"/\";\n }\n\n return `${normalizedBasePath}/${cleanSlug}`.replace(/\\/+/g, \"/\");\n}\n\nexport function buildAuthorPath(\n basePath: string | undefined,\n authorSlug: string,\n): string {\n return buildBlogPath(basePath, `authors/${authorSlug}`);\n}\n\nexport function getPathPrefixFromBlogUrl(blogUrl: string): string {\n const parsed = new URL(blogUrl);\n return normalizeBlogBasePath(parsed.pathname);\n}\n","/**\n * Structured Data (JSON-LD) utilities for SEO optimization\n *\n * This module provides comprehensive schema.org structured data generation\n * for blog articles, authors, and organizations. It follows Google's\n * recommended guidelines for structured data markup.\n *\n * @see https://developers.google.com/search/docs/appearance/structured-data\n * @see https://schema.org/\n */\n\nimport type {\n PublishedArticle,\n PublishedAuthor,\n PublishedSite,\n} from \"../types/contracts\";\nimport { buildAuthorPath } from \"./urls\";\n\n/**\n * Base schema.org context and type\n */\ninterface BaseStructuredData {\n \"@context\": \"https://schema.org\";\n \"@type\": string;\n \"@id\"?: string;\n}\n\n/**\n * Person schema for authors\n * @see https://schema.org/Person\n */\nexport interface PersonSchema extends BaseStructuredData {\n \"@type\": \"Person\";\n name: string;\n description?: string;\n identifier?: string;\n image?: string;\n url?: string;\n sameAs?: string[];\n jobTitle?: string;\n affiliation?: OrganizationSchema;\n knowsAbout?: string[];\n additionalType?: string;\n}\n\n/**\n * Organization schema for blog sites\n * @see https://schema.org/Organization\n */\nexport interface OrganizationSchema extends BaseStructuredData {\n \"@type\": \"Organization\";\n name: string;\n description?: string;\n url?: string;\n logo?: string;\n sameAs?: string[];\n foundingDate?: string;\n location?: string;\n contactPoint?: {\n \"@type\": \"ContactPoint\";\n contactType: string;\n url?: string;\n email?: string;\n };\n}\n\n/**\n * BlogPosting schema for articles\n * @see https://schema.org/BlogPosting\n */\nexport interface BlogPostingSchema extends BaseStructuredData {\n \"@type\": \"BlogPosting\";\n headline: string;\n description?: string;\n image?: string | string[];\n datePublished: string;\n dateModified?: string;\n author?: PersonSchema | PersonSchema[];\n publisher: OrganizationSchema;\n mainEntityOfPage: {\n \"@type\": \"WebPage\";\n \"@id\": string;\n };\n keywords?: string | string[];\n wordCount?: number;\n timeRequired?: string; // ISO 8601 duration format (PT5M = 5 minutes)\n inLanguage?: string;\n isAccessibleForFree?: boolean;\n genre?: string | string[];\n about?: {\n \"@type\": \"Thing\";\n name: string;\n }[];\n mentions?: {\n \"@type\": \"Thing\";\n name: string;\n }[];\n}\n\n/**\n * WebSite schema for the blog home page\n * @see https://schema.org/WebSite\n */\nexport interface WebSiteSchema extends BaseStructuredData {\n \"@type\": \"WebSite\";\n name: string;\n description?: string;\n url: string;\n publisher: OrganizationSchema;\n inLanguage?: string;\n potentialAction?: {\n \"@type\": \"SearchAction\";\n target: {\n \"@type\": \"EntryPoint\";\n urlTemplate: string;\n };\n \"query-input\": string;\n };\n}\n\n/**\n * BreadcrumbList schema for navigation\n * @see https://schema.org/BreadcrumbList\n */\nexport interface BreadcrumbListSchema extends BaseStructuredData {\n \"@type\": \"BreadcrumbList\";\n itemListElement: {\n \"@type\": \"ListItem\";\n position: number;\n name: string;\n item: string;\n }[];\n}\n\n/**\n * Options for customizing structured data generation\n */\nexport interface StructuredDataOptions {\n /** Include optional properties like keywords, mentions, etc. */\n includeOptionalProperties?: boolean;\n /** Include search action in WebSite schema */\n includeSearchAction?: boolean;\n /** Custom domain override for URLs */\n customDomain?: string;\n /** Path prefix for blog URLs (e.g., '/blog', '/articles') */\n pathPrefix?: string;\n /** Language code (e.g., 'en-US') */\n language?: string;\n /** Whether content is free to access */\n isAccessibleForFree?: boolean;\n}\n\n/**\n * Generate comprehensive structured data for a blog article\n */\nexport function generateArticleStructuredData(\n article: PublishedArticle,\n options: StructuredDataOptions = {},\n): BlogPostingSchema {\n const {\n customDomain,\n pathPrefix = \"/blog\",\n language,\n isAccessibleForFree = true,\n includeOptionalProperties = true,\n } = options;\n\n const domain = customDomain ?? article.site.domain;\n const canonicalUrl = customDomain\n ? `https://${domain}${pathPrefix}/${article.slug}`\n : (article.meta.canonicalUrl ??\n `https://${domain}${pathPrefix}/${article.slug}`);\n\n // Generate author schema\n const authorSchema = article.author\n ? generateAuthorStructuredData(article.author, { customDomain, pathPrefix })\n : undefined;\n\n // Generate publisher schema\n const publisherSchema = generateOrganizationStructuredData(article.site, {\n customDomain,\n pathPrefix,\n });\n\n // Convert reading seconds to ISO 8601 duration\n const readingMinutes = Math.max(1, Math.ceil(article.readingSeconds / 60));\n const timeRequired = `PT${readingMinutes}M`;\n\n const schema: BlogPostingSchema = {\n \"@context\": \"https://schema.org\",\n \"@type\": \"BlogPosting\",\n \"@id\": `${canonicalUrl}#article`,\n headline: article.title,\n description: article.excerpt,\n datePublished: article.publishedAt,\n dateModified: article.updatedAt,\n author: authorSchema,\n publisher: publisherSchema,\n mainEntityOfPage: {\n \"@type\": \"WebPage\",\n \"@id\": canonicalUrl,\n },\n wordCount: article.wordCount,\n timeRequired,\n isAccessibleForFree,\n };\n\n // Add optional properties if enabled\n if (includeOptionalProperties) {\n // Featured image\n if (article.featuredImage) {\n schema.image = article.featuredImage;\n }\n\n // Keywords\n if (article.meta.keywords.length > 0) {\n schema.keywords = [...article.meta.keywords];\n }\n\n // Language\n if (language ?? article.site.locale) {\n schema.inLanguage = language ?? article.site.locale;\n }\n\n // Extract topics from tone adjectives or keywords for 'about' property\n if (article.site.toneAdjectives.length > 0) {\n schema.about = article.site.toneAdjectives.map((topic) => ({\n \"@type\": \"Thing\" as const,\n name: topic,\n }));\n }\n\n // Genre based on site description or tone\n if (article.site.toneAdjectives.length > 0) {\n schema.genre = [...article.site.toneAdjectives];\n }\n }\n\n return schema;\n}\n\n/**\n * Generate structured data for an author\n */\nexport function generateAuthorStructuredData(\n author: PublishedAuthor,\n options: StructuredDataOptions = {},\n): PersonSchema {\n const { customDomain, pathPrefix = \"/blog\" } = options;\n\n const schema: PersonSchema = {\n \"@context\": \"https://schema.org\",\n \"@type\": \"Person\",\n \"@id\": `#author-${author.id}`,\n name: author.name,\n identifier: author.id,\n };\n\n // Add optional properties\n if (author.bio) {\n schema.description = author.bio;\n }\n\n if (author.avatarUrl) {\n schema.image = author.avatarUrl;\n }\n\n const sameAs = [\n author.socialLinks?.website,\n author.socialLinks?.x,\n author.socialLinks?.linkedin,\n author.socialLinks?.github,\n ].filter((url): url is string => Boolean(url));\n\n if (sameAs.length > 0) {\n schema.sameAs = sameAs;\n }\n\n if (author.slug?.trim()) {\n const authorUrl = customDomain\n ? `https://${customDomain}${buildAuthorPath(pathPrefix, author.slug)}`\n : buildAuthorPath(pathPrefix, author.slug);\n schema.url = authorUrl;\n }\n\n // Additional type for guest authors\n if (author.isGuest) {\n schema.additionalType = \"GuestAuthor\";\n }\n\n // Add knowledge areas from tone adjectives\n if (author.toneAdjectives && author.toneAdjectives.length > 0) {\n schema.knowsAbout = [...author.toneAdjectives];\n }\n\n return schema;\n}\n\n/**\n * Generate structured data for a blog site organization\n */\nexport function generateOrganizationStructuredData(\n site: PublishedSite,\n options: StructuredDataOptions = {},\n): OrganizationSchema {\n const { customDomain, pathPrefix = \"/blog\" } = options;\n\n const domain = customDomain ?? site.domain;\n const siteUrl = `https://${domain}${pathPrefix}`;\n\n const schema: OrganizationSchema = {\n \"@context\": \"https://schema.org\",\n \"@type\": \"Organization\",\n \"@id\": `${siteUrl}#organization`,\n name: site.name,\n url: siteUrl,\n };\n\n // Add optional properties\n if (site.description?.trim()) {\n schema.description = site.description;\n }\n\n if (site.tagline?.trim()) {\n schema.description = schema.description\n ? `${schema.description}. ${site.tagline}`\n : site.tagline;\n }\n\n return schema;\n}\n\n/**\n * Generate structured data for the blog website\n */\nexport function generateWebSiteStructuredData(\n site: PublishedSite,\n options: StructuredDataOptions = {},\n): WebSiteSchema {\n const {\n customDomain,\n pathPrefix = \"/blog\",\n language,\n includeSearchAction = true,\n } = options;\n\n const domain = customDomain ?? site.domain;\n const siteUrl = `https://${domain}${pathPrefix}`;\n\n const publisherSchema = generateOrganizationStructuredData(site, options);\n\n const schema: WebSiteSchema = {\n \"@context\": \"https://schema.org\",\n \"@type\": \"WebSite\",\n \"@id\": `${siteUrl}#website`,\n name: site.name,\n url: siteUrl,\n publisher: publisherSchema,\n };\n\n // Add optional properties\n if (site.description?.trim()) {\n schema.description = site.description;\n }\n\n if (language ?? site.locale) {\n schema.inLanguage = language ?? site.locale;\n }\n\n // Add search action for better search engine integration\n if (includeSearchAction) {\n schema.potentialAction = {\n \"@type\": \"SearchAction\",\n target: {\n \"@type\": \"EntryPoint\",\n urlTemplate: `${siteUrl}?search={search_term_string}`,\n },\n \"query-input\": \"required name=search_term_string\",\n };\n }\n\n return schema;\n}\n\n/**\n * Generate breadcrumb structured data for navigation\n */\nexport function generateBreadcrumbStructuredData(\n breadcrumbs: Array<{ name: string; url: string }>,\n options: StructuredDataOptions = {},\n): BreadcrumbListSchema {\n const { customDomain } = options;\n\n return {\n \"@context\": \"https://schema.org\",\n \"@type\": \"BreadcrumbList\",\n itemListElement: breadcrumbs.map((crumb, index) => ({\n \"@type\": \"ListItem\" as const,\n position: index + 1,\n name: crumb.name,\n item:\n customDomain && !crumb.url.startsWith(\"http\")\n ? `https://${customDomain}${crumb.url}`\n : crumb.url,\n })),\n };\n}\n\n/**\n * Generate combined structured data for a complete article page\n */\nexport function generateCompleteArticleStructuredData(\n article: PublishedArticle,\n options: StructuredDataOptions = {},\n): Array<BlogPostingSchema | WebSiteSchema | BreadcrumbListSchema> {\n const schemas: Array<\n BlogPostingSchema | WebSiteSchema | BreadcrumbListSchema\n > = [];\n\n // Article schema\n schemas.push(generateArticleStructuredData(article, options));\n\n // Website schema\n schemas.push(generateWebSiteStructuredData(article.site, options));\n\n // Breadcrumb schema for article pages\n const pathPrefix = options.pathPrefix ?? \"/blog\";\n const breadcrumbs = [\n { name: \"Home\", url: \"/\" },\n { name: article.site.name, url: pathPrefix },\n { name: article.title, url: `${pathPrefix}/${article.slug}` },\n ];\n schemas.push(generateBreadcrumbStructuredData(breadcrumbs, options));\n\n return schemas;\n}\n\n/**\n * Generate structured data for the blog home page\n */\nexport function generateBlogHomeStructuredData(\n site: PublishedSite,\n featuredArticles: PublishedArticle[] = [],\n options: StructuredDataOptions = {},\n): Array<WebSiteSchema | BlogPostingSchema> {\n const schemas: Array<WebSiteSchema | BlogPostingSchema> = [];\n\n // Website schema for the home page\n schemas.push(generateWebSiteStructuredData(site, options));\n\n // Featured articles schemas (limit to first 3-5 for performance)\n if (featuredArticles.length > 0) {\n const articleSchemas = featuredArticles\n .slice(0, 5)\n .map((article) => generateArticleStructuredData(article, options));\n schemas.push(...articleSchemas);\n }\n\n return schemas;\n}\n\n/**\n * Validate structured data schema\n */\nexport function validateStructuredData(schema: BaseStructuredData): {\n isValid: boolean;\n errors: string[];\n} {\n const errors: string[] = [];\n\n // Check required fields\n if (!schema[\"@context\"]) {\n errors.push(\"Missing required @context property\");\n } else if (schema[\"@context\"] !== \"https://schema.org\") {\n errors.push(\"@context must be 'https://schema.org'\");\n }\n\n if (!schema[\"@type\"]) {\n errors.push(\"Missing required @type property\");\n }\n\n // Type-specific validations\n if (schema[\"@type\"] === \"BlogPosting\") {\n const blogSchema = schema as BlogPostingSchema;\n if (!blogSchema.headline) {\n errors.push(\"BlogPosting: Missing required headline\");\n }\n if (!blogSchema.datePublished) {\n errors.push(\"BlogPosting: Missing required datePublished\");\n }\n if (!blogSchema.author) {\n errors.push(\"BlogPosting: Missing required author\");\n }\n if (!blogSchema.publisher) {\n errors.push(\"BlogPosting: Missing required publisher\");\n }\n }\n\n if (schema[\"@type\"] === \"Person\") {\n const personSchema = schema as PersonSchema;\n if (!personSchema.name) {\n errors.push(\"Person: Missing required name\");\n }\n }\n\n if (schema[\"@type\"] === \"Organization\") {\n const orgSchema = schema as OrganizationSchema;\n if (!orgSchema.name) {\n errors.push(\"Organization: Missing required name\");\n }\n }\n\n return {\n isValid: errors.length === 0,\n errors,\n };\n}\n\n/**\n * Convert structured data to JSON-LD string for HTML embedding\n */\nexport function structuredDataToJsonLd(\n schema: BaseStructuredData | BaseStructuredData[],\n): string {\n return JSON.stringify(schema, null, 0);\n}\n\n/**\n * Create a React script element for JSON-LD structured data\n */\nexport function createStructuredDataScript(\n schema: BaseStructuredData | BaseStructuredData[],\n) {\n return {\n type: \"application/ld+json\",\n dangerouslySetInnerHTML: {\n __html: structuredDataToJsonLd(schema),\n },\n };\n}\n\n/**\n * Extract keywords from article content for structured data\n */\nexport function extractKeywordsFromArticle(\n article: PublishedArticle,\n): string[] {\n const keywords = new Set<string>();\n\n // Add meta keywords\n article.meta.keywords.forEach((keyword) => keywords.add(keyword));\n\n // Add site tone adjectives as topical keywords\n article.site.toneAdjectives.forEach((tone) => keywords.add(tone));\n\n // Add author tone adjectives\n if (article.author) {\n article.author.toneAdjectives.forEach((tone) => keywords.add(tone));\n }\n\n return Array.from(keywords);\n}\n\n/**\n * Error types for structured data operations\n */\nexport class StructuredDataError extends Error {\n constructor(\n message: string,\n public readonly code: string,\n public readonly details?: unknown,\n ) {\n super(message);\n this.name = \"StructuredDataError\";\n }\n}\n\n/**\n * Generate structured data with error handling\n */\nexport function safeGenerateArticleStructuredData(\n article: PublishedArticle,\n options: StructuredDataOptions = {},\n): { schema?: BlogPostingSchema; error?: StructuredDataError } {\n try {\n const schema = generateArticleStructuredData(article, options);\n const validation = validateStructuredData(schema);\n\n if (!validation.isValid) {\n return {\n error: new StructuredDataError(\n \"Generated schema validation failed\",\n \"VALIDATION_FAILED\",\n validation.errors,\n ),\n };\n }\n\n return { schema };\n } catch (error) {\n return {\n error: new StructuredDataError(\n \"Failed to generate structured data\",\n \"GENERATION_FAILED\",\n error,\n ),\n };\n }\n}\n","import { format, formatDistanceToNow } from \"date-fns\";\nimport type { CSSProperties } from \"react\";\n\nexport interface BlogTheme {\n accentColor?: string;\n accentHoverColor?: string;\n textAccentColor?: string;\n textAccentHoverColor?: string;\n accentBackgroundColor?: string;\n accentBorderColor?: string;\n}\n\nexport interface TocItem {\n id: string;\n text: string;\n level: 2 | 3;\n}\n\nexport interface ArticleDateMeta {\n publishedDateLabel: string;\n publishedRelativeLabel: string;\n updatedDateLabel: string;\n isUpdated: boolean;\n}\n\nexport interface TocItemState {\n isActive: boolean;\n ariaCurrent: \"location\" | undefined;\n}\n\nexport type BlogThemeStyle = CSSProperties & {\n \"--blog-accent\": string;\n \"--blog-accent-hover\": string;\n \"--blog-text-accent\": string;\n \"--blog-text-accent-hover\": string;\n \"--blog-accent-bg\": string;\n \"--blog-accent-border\": string;\n};\n\nconst DEFAULT_THEME: Required<BlogTheme> = {\n accentColor: \"hsl(var(--primary))\",\n accentHoverColor: \"hsl(var(--primary))\",\n textAccentColor: \"hsl(var(--primary))\",\n textAccentHoverColor: \"hsl(var(--primary))\",\n accentBackgroundColor: \"hsl(var(--primary) / 0.08)\",\n accentBorderColor: \"hsl(var(--primary) / 0.25)\",\n};\n\nexport function getBlogThemeStyle(theme: BlogTheme = {}): BlogThemeStyle {\n return {\n \"--blog-accent\": theme.accentColor ?? DEFAULT_THEME.accentColor,\n \"--blog-accent-hover\":\n theme.accentHoverColor ?? DEFAULT_THEME.accentHoverColor,\n \"--blog-text-accent\":\n theme.textAccentColor ?? theme.accentColor ?? DEFAULT_THEME.textAccentColor,\n \"--blog-text-accent-hover\":\n theme.textAccentHoverColor ??\n theme.accentHoverColor ??\n DEFAULT_THEME.textAccentHoverColor,\n \"--blog-accent-bg\":\n theme.accentBackgroundColor ?? DEFAULT_THEME.accentBackgroundColor,\n \"--blog-accent-border\":\n theme.accentBorderColor ?? DEFAULT_THEME.accentBorderColor,\n };\n}\n\nexport function formatArticleDateMeta(\n publishedAt: string,\n updatedAt: string,\n): ArticleDateMeta {\n const publishedDate = new Date(publishedAt);\n const updatedDate = new Date(updatedAt);\n\n return {\n publishedDateLabel: format(publishedDate, \"d MMMM yyyy\"),\n publishedRelativeLabel: formatDistanceToNow(publishedDate, {\n addSuffix: true,\n }),\n updatedDateLabel: format(updatedDate, \"d MMMM yyyy\"),\n isUpdated: updatedDate.getTime() !== publishedDate.getTime(),\n };\n}\n\nexport function extractTableOfContents(markdown: string): TocItem[] {\n const items: TocItem[] = [];\n let inFence = false;\n\n for (const line of markdown.split(\"\\n\")) {\n if (/^\\s*```/.test(line)) {\n inFence = !inFence;\n continue;\n }\n\n if (inFence) {\n continue;\n }\n\n const match = /^(#{2,3})\\s+(.+?)\\s*#*\\s*$/.exec(line);\n if (!match?.[1] || !match[2]) {\n continue;\n }\n\n const text = stripMarkdownInline(match[2]);\n if (!text) {\n continue;\n }\n\n items.push({\n id: slugifyHeading(text),\n text,\n level: match[1].length as 2 | 3,\n });\n }\n\n return items;\n}\n\nexport function formatTableOfContentsSummary(count: number): string {\n return `${count} ${count === 1 ? \"section\" : \"sections\"}`;\n}\n\nexport function normalizeReadingProgress(progress: number): number {\n if (!Number.isFinite(progress)) {\n return 0;\n }\n\n return Math.min(100, Math.max(0, progress));\n}\n\nexport function getTocItemState(\n itemId: string,\n activeItemId: string | null,\n): TocItemState {\n const isActive = itemId === activeItemId;\n\n return {\n isActive,\n ariaCurrent: isActive ? \"location\" : undefined,\n };\n}\n\nfunction stripMarkdownInline(value: string): string {\n return value\n .replace(/\\[([^\\]]+)\\]\\([^)]+\\)/g, \"$1\")\n .replace(/[*_`~]/g, \"\")\n .replace(/<[^>]+>/g, \"\")\n .replace(/\\s+/g, \" \")\n .trim();\n}\n\nfunction slugifyHeading(value: string): string {\n return value\n .toLowerCase()\n .replace(/[^a-z0-9\\s-]/g, \"\")\n .trim()\n .replace(/\\s+/g, \"-\")\n .replace(/-+/g, \"-\");\n}\n","\"use client\";\n\nimport { useState, useSyncExternalStore, type FormEvent } from \"react\";\nimport { ArrowUpRight, Check } from \"lucide-react\";\n\nimport { cn } from \"../lib/utils\";\nimport type { PublishedNewsletterSettings } from \"../types/contracts\";\n\nexport const NEWSLETTER_SUCCESS_MESSAGE =\n \"Thanks, you're on the list. We'll confirm before sending updates.\";\n\nexport interface NewsletterSignupProps {\n siteId: string;\n settings: PublishedNewsletterSettings;\n sourceSurface: \"blog_home\" | \"article\";\n sourceArticleSlug?: string;\n sourceUrl?: string;\n previewMode?: boolean;\n className?: string;\n}\n\nexport function NewsletterSignup({\n siteId,\n settings,\n sourceSurface,\n sourceArticleSlug,\n sourceUrl,\n previewMode = false,\n className,\n}: NewsletterSignupProps) {\n const [message, setMessage] = useState<string | null>(null);\n const [error, setError] = useState<string | null>(null);\n const [hasSubmitted, setHasSubmitted] = useState(false);\n const [isSubmitting, setIsSubmitting] = useState(false);\n const subscriptionKey = getSubscriptionStorageKey(siteId);\n const hasStoredSubscribed = useSyncExternalStore(\n subscribeToStoredSubscription,\n () => hasStoredSubscription(subscriptionKey),\n () => false,\n );\n const hasSubscribed = hasSubmitted || (!previewMode && hasStoredSubscribed);\n\n async function handleSubmit(event: FormEvent<HTMLFormElement>) {\n event.preventDefault();\n setError(null);\n setMessage(null);\n\n const formData = new FormData(event.currentTarget);\n const honeypot = getFormString(formData, \"company\");\n\n if (previewMode) {\n setMessage(NEWSLETTER_SUCCESS_MESSAGE);\n setHasSubmitted(true);\n event.currentTarget.reset();\n return;\n }\n\n setIsSubmitting(true);\n try {\n const response = await fetch(\n `${settings.captureBaseUrl.replace(/\\/$/, \"\")}/api/newsletter/subscribe`,\n {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({\n siteId: Number(siteId),\n publicSubscribeToken: settings.publicSubscribeToken,\n email: getFormString(formData, \"email\"),\n name: getOptionalFormString(formData, \"name\"),\n sourceSurface,\n sourceUrl: resolveSourceUrl(sourceUrl),\n sourceArticleSlug: sourceArticleSlug ?? null,\n honeypot,\n }),\n },\n );\n\n if (!response.ok) {\n throw new Error(\"Newsletter signup failed.\");\n }\n\n const result: unknown = await response.json().catch(() => null);\n const successMessage =\n getNewsletterResponseMessage(result) ?? NEWSLETTER_SUCCESS_MESSAGE;\n\n storeSubscription(subscriptionKey);\n setMessage(successMessage);\n setHasSubmitted(true);\n event.currentTarget.reset();\n } catch {\n setMessage(null);\n setError(\"Newsletter signup failed. Please try again.\");\n } finally {\n setIsSubmitting(false);\n }\n }\n\n return (\n <section\n className={cn(\n \"border-y border-[var(--blog-accent-border)] py-5 sm:py-6\",\n className,\n )}\n aria-labelledby={`newsletter-${sourceSurface}-title`}\n >\n <div className=\"grid gap-4 lg:grid-cols-[minmax(0,0.9fr)_minmax(0,1.4fr)] lg:items-end\">\n <div className=\"max-w-xl space-y-1\">\n <h2\n id={`newsletter-${sourceSurface}-title`}\n className=\"text-base leading-6 font-semibold\"\n >\n {settings.title}\n </h2>\n <p className=\"text-muted-foreground text-sm leading-6\">\n {settings.description}\n </p>\n </div>\n\n {hasSubscribed ? (\n <div\n className=\"flex items-start gap-3 text-sm leading-6 text-emerald-500\"\n role=\"status\"\n aria-live=\"polite\"\n >\n <span className=\"mt-0.5 inline-flex size-5 shrink-0 items-center justify-center rounded-full bg-emerald-500/15\">\n <Check className=\"size-3.5\" aria-hidden=\"true\" />\n </span>\n <p>{message ?? NEWSLETTER_SUCCESS_MESSAGE}</p>\n </div>\n ) : (\n <form onSubmit={handleSubmit} className=\"space-y-3\">\n <div className=\"grid gap-2 sm:grid-cols-[minmax(0,0.8fr)_minmax(0,1fr)_auto]\">\n <label\n className=\"sr-only\"\n htmlFor={`newsletter-name-${sourceSurface}`}\n >\n Name\n </label>\n <input\n id={`newsletter-name-${sourceSurface}`}\n name=\"name\"\n type=\"text\"\n autoComplete=\"name\"\n placeholder=\"Name\"\n className=\"border-input bg-background text-foreground placeholder:text-muted-foreground focus-visible:ring-ring min-h-10 rounded-md border px-3 py-2 text-sm focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-none\"\n />\n\n <label\n className=\"sr-only\"\n htmlFor={`newsletter-email-${sourceSurface}`}\n >\n Email\n </label>\n <input\n id={`newsletter-email-${sourceSurface}`}\n name=\"email\"\n type=\"email\"\n autoComplete=\"email\"\n placeholder=\"Email address\"\n required\n className=\"border-input bg-background text-foreground placeholder:text-muted-foreground focus-visible:ring-ring min-h-10 rounded-md border px-3 py-2 text-sm focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-none\"\n />\n\n <input\n type=\"text\"\n name=\"company\"\n tabIndex={-1}\n autoComplete=\"off\"\n aria-hidden=\"true\"\n className=\"hidden\"\n />\n\n <button\n type=\"submit\"\n disabled={isSubmitting}\n className=\"inline-flex min-h-10 w-full shrink-0 items-center justify-center gap-2 rounded-full bg-[var(--blog-accent)] px-5 py-2 text-sm font-semibold text-white transition-opacity hover:opacity-90 disabled:cursor-not-allowed disabled:opacity-60 sm:w-auto\"\n >\n {isSubmitting ? \"Submitting...\" : settings.buttonLabel}\n <ArrowUpRight className=\"size-4\" aria-hidden=\"true\" />\n </button>\n </div>\n\n {error && <p className=\"text-sm text-red-600\">{error}</p>}\n </form>\n )}\n </div>\n </section>\n );\n}\n\nfunction resolveSourceUrl(sourceUrl: string | undefined): string | null {\n if (sourceUrl?.startsWith(\"http://\") || sourceUrl?.startsWith(\"https://\")) {\n return sourceUrl;\n }\n\n if (typeof window !== \"undefined\") {\n return window.location.href;\n }\n\n return null;\n}\n\nfunction getFormString(formData: FormData, key: string): string {\n const value = formData.get(key);\n return typeof value === \"string\" ? value : \"\";\n}\n\nfunction getOptionalFormString(formData: FormData, key: string): string | null {\n const value = getFormString(formData, key).trim();\n if (value.length === 0) {\n return null;\n }\n\n return value;\n}\n\nfunction getSubscriptionStorageKey(siteId: string): string {\n return `bloggy_newsletter_subscribed_${siteId}`;\n}\n\nfunction hasStoredSubscription(key: string): boolean {\n if (typeof window === \"undefined\") {\n return false;\n }\n\n try {\n if (window.localStorage.getItem(key) === \"true\") {\n return true;\n }\n } catch {\n // Ignore storage failures; the subscription API remains the source of truth.\n }\n\n if (typeof document === \"undefined\") {\n return false;\n }\n\n return document.cookie\n .split(\";\")\n .some((cookie) => cookie.trim().startsWith(`${key}=true`));\n}\n\nfunction storeSubscription(key: string): void {\n if (typeof window !== \"undefined\") {\n try {\n window.localStorage.setItem(key, \"true\");\n } catch {\n // Ignore storage failures; users can still submit normally.\n }\n }\n\n if (typeof document !== \"undefined\") {\n document.cookie = `${key}=true; Max-Age=31536000; Path=/; SameSite=Lax`;\n }\n}\n\nfunction subscribeToStoredSubscription(callback: () => void): () => void {\n if (typeof window === \"undefined\") {\n return () => undefined;\n }\n\n window.addEventListener(\"storage\", callback);\n return () => window.removeEventListener(\"storage\", callback);\n}\n\nfunction getNewsletterResponseMessage(value: unknown): string | null {\n if (\n value &&\n typeof value === \"object\" &&\n \"message\" in value &&\n typeof value.message === \"string\"\n ) {\n return value.message;\n }\n\n return null;\n}\n","import React from \"react\";\nimport Link from \"next/link\";\nimport Image from \"next/image\";\nimport {\n type PublishedArticle,\n type PublishedAuthor,\n type PublishedNewsletterSettings,\n type PublishedSite,\n} from \"../../types/contracts\";\nimport { cn } from \"../../lib/utils\";\nimport Pagination from \"../../components/Pagination\";\nimport {\n generateBlogHomeStructuredData,\n createStructuredDataScript,\n} from \"../../lib/structured-data\";\nimport {\n buildAuthorPath,\n buildBlogPath,\n normalizeBlogBasePath,\n} from \"../../lib/urls\";\nimport { formatDistanceToNow } from \"date-fns\";\nimport { type BlogTheme, getBlogThemeStyle } from \"../../lib/article-ui\";\nimport { NewsletterSignup } from \"../../components/NewsletterSignup\";\n\ninterface BlogHomePageProps {\n articles: PublishedArticle[];\n siteName?: string;\n siteTagline?: string;\n className?: string;\n /** Site data for structured data generation */\n site?: PublishedSite;\n /** Whether to include structured data */\n includeStructuredData?: boolean;\n /** Public path where this blog is mounted, e.g. \"/blog\" or \"/new-blog\". */\n basePath?: string;\n /** Pagination configuration */\n pagination?: {\n currentPage: number;\n totalPages: number;\n baseUrl?: string;\n };\n /** Optional theme values for host-site brand integration. */\n theme?: BlogTheme;\n /** Optional Bloggy-owned newsletter capture configuration. */\n newsletter?: PublishedNewsletterSettings;\n /** Render interactive preview success without persisting subscribers. */\n newsletterPreviewMode?: boolean;\n}\n\n/**\n * Blog home page component that displays a list of published articles.\n *\n * This component is designed to be used by customers who install the\n * @xexr/blog-platform package. It provides a clean, SEO-friendly\n * article listing with proper metadata.\n */\nexport default function BlogHomePage({\n articles,\n siteName,\n siteTagline,\n className,\n site,\n includeStructuredData = false,\n basePath = \"/blog\",\n pagination,\n theme,\n newsletter,\n newsletterPreviewMode = false,\n}: BlogHomePageProps) {\n const normalizedBasePath = normalizeBlogBasePath(basePath) || \"/\";\n const newsletterSettings = newsletter ?? site?.newsletter;\n const newsletterSiteId = site?.id ?? articles[0]?.site.id;\n\n return (\n <div\n style={getBlogThemeStyle(theme)}\n className={cn(\n \"blog-home-page container mx-auto max-w-5xl px-4 py-8 sm:px-6 sm:py-12 lg:px-8 lg:py-16\",\n className,\n )}\n >\n {/* Site Header */}\n {siteName && (\n <header className=\"blog-header mb-8 text-center sm:mb-12 lg:mb-16\">\n <h1 className=\"blog-title mb-2 bg-linear-to-r from-[var(--blog-accent-hover)] to-[var(--blog-accent)] bg-clip-text text-3xl font-semibold tracking-tight text-balance text-transparent sm:text-4xl lg:text-5xl\">\n {siteName}\n </h1>\n {siteTagline && (\n <p className=\"blog-tagline text-muted-foreground text-base sm:text-lg\">\n {siteTagline}\n </p>\n )}\n </header>\n )}\n\n {/* Articles List */}\n <main className=\"articles-list\">\n {articles.length === 0 ? (\n <div className=\"no-articles text-muted-foreground py-16 text-center sm:py-24 lg:py-32\">\n <h2 className=\"mb-3 text-xl font-light sm:mb-4 sm:text-2xl lg:text-3xl\">\n No articles yet\n </h2>\n <p className=\"text-muted-foreground/70 mx-auto max-w-md text-base sm:text-lg\">\n This blog doesn&apos;t have any published articles yet.\n </p>\n </div>\n ) : (\n <div className=\"space-y-0\">\n {articles.map((article) => (\n <ArticlePreview\n key={article.id}\n article={article}\n basePath={normalizedBasePath}\n />\n ))}\n </div>\n )}\n\n {/* Pagination */}\n {pagination && pagination.totalPages > 1 && (\n <div className=\"pagination-wrapper mt-12\">\n <Pagination\n currentPage={pagination.currentPage}\n totalPages={pagination.totalPages}\n baseUrl={pagination.baseUrl ?? normalizedBasePath}\n className=\"justify-center\"\n />\n </div>\n )}\n </main>\n\n {newsletterSettings?.enabled && newsletterSiteId && (\n <NewsletterSignup\n siteId={newsletterSiteId}\n settings={newsletterSettings}\n sourceSurface=\"blog_home\"\n previewMode={newsletterPreviewMode}\n className=\"mt-10 sm:mt-12\"\n />\n )}\n\n {/* JSON-LD Structured Data */}\n {includeStructuredData &&\n site &&\n (() => {\n const structuredDataProps = createStructuredDataScript(\n generateBlogHomeStructuredData(site, articles.slice(0, 5), {\n pathPrefix: normalizedBasePath,\n }),\n );\n return (\n <script\n type={structuredDataProps.type}\n dangerouslySetInnerHTML={\n structuredDataProps.dangerouslySetInnerHTML\n }\n />\n );\n })()}\n </div>\n );\n}\n\n/**\n * Helper function to format reading time in minutes\n */\nfunction formatReadingTime(seconds: number): string {\n const minutes = Math.ceil(seconds / 60);\n return `${minutes} min read`;\n}\n\n/**\n * Individual article preview component for the blog listing.\n */\nfunction ArticlePreview({\n article,\n basePath,\n}: {\n article: PublishedArticle;\n basePath: string;\n}) {\n const articleUrl = buildBlogPath(basePath, article.slug);\n const formattedDate = formatDistanceToNow(new Date(article.publishedAt), {\n addSuffix: true,\n });\n const readingTime = formatReadingTime(article.readingSeconds);\n\n // Use the featured image URL provided by Bloggy (hosted on Bloggy's domain)\n const imageUrl = article.featuredImage;\n\n return (\n <article className=\"group border-border mb-6 block border-b pb-6 last:mb-0 last:border-b-0 last:pb-0 sm:mb-8 sm:pb-8\">\n {/* Mobile/Small Tablet: Vertical layout */}\n <div className=\"space-y-4 lg:hidden\">\n {imageUrl && (\n <Link\n href={articleUrl}\n className=\"focus-visible:ring-ring relative block aspect-[16/10] w-full overflow-hidden rounded-2xl focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-none\"\n aria-label={`Read article: ${article.title}`}\n >\n <Image\n src={imageUrl}\n alt={\n article.featuredImageAlt ??\n `Featured image for ${article.title}`\n }\n width={400}\n height={250}\n className=\"h-full w-full object-cover transition-transform duration-300 group-hover:scale-105\"\n />\n </Link>\n )}\n\n <div className=\"space-y-3\">\n <Link\n href={articleUrl}\n className=\"focus-visible:ring-ring block rounded-md hover:no-underline focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-none\"\n >\n <h2 className=\"text-lg leading-tight font-bold text-balance transition-colors group-hover:text-[var(--blog-accent)] sm:text-xl md:text-2xl\">\n {article.title}\n </h2>\n </Link>\n\n <div className=\"text-muted-foreground flex flex-wrap items-center gap-x-3 gap-y-1 text-sm\">\n {article.author && (\n <>\n <AuthorLink author={article.author} basePath={basePath} />\n <span className=\"text-border\">•</span>\n </>\n )}\n <time\n dateTime={article.publishedAt}\n className=\"font-medium\"\n aria-label={`Published ${formattedDate}`}\n >\n {formattedDate}\n </time>\n <span className=\"text-border\">•</span>\n <span className=\"font-medium\">{readingTime}</span>\n </div>\n\n {article.excerpt && (\n <p className=\"text-muted-foreground line-clamp-3 text-sm leading-relaxed sm:text-base\">\n {article.excerpt}\n </p>\n )}\n\n {(article.topics ?? []).length > 0 && (\n <div className=\"flex flex-wrap gap-2\">\n {(article.topics ?? []).map((topic) => (\n <span\n key={topic.id}\n className=\"rounded-full border border-[var(--blog-accent-border)] px-2.5 py-1 text-xs font-medium text-[var(--blog-text-accent)]\"\n >\n {topic.name}\n </span>\n ))}\n </div>\n )}\n </div>\n </div>\n\n {/* Large Tablet/Desktop: Horizontal layout */}\n <div className=\"hidden items-start gap-6 lg:flex xl:gap-8\">\n {imageUrl && (\n <Link\n href={articleUrl}\n className=\"focus-visible:ring-ring relative block aspect-[16/10] w-64 shrink-0 overflow-hidden rounded-2xl focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-none xl:w-72\"\n aria-label={`Read article: ${article.title}`}\n >\n <Image\n src={imageUrl}\n alt={\n article.featuredImageAlt ??\n `Featured image for ${article.title}`\n }\n width={288}\n height={180}\n className=\"h-full w-full object-cover transition-transform duration-300 group-hover:scale-105\"\n />\n </Link>\n )}\n\n <div className=\"flex min-h-[180px] flex-1 flex-col justify-between space-y-4 xl:min-h-[200px]\">\n <div className=\"space-y-4\">\n <Link\n href={articleUrl}\n className=\"focus-visible:ring-ring block rounded-md hover:no-underline focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-none\"\n >\n <h2 className=\"text-2xl leading-tight font-bold text-balance transition-colors group-hover:text-[var(--blog-accent)] xl:text-3xl\">\n {article.title}\n </h2>\n </Link>\n\n {article.excerpt && (\n <p className=\"text-muted-foreground line-clamp-3 text-base leading-relaxed xl:text-lg\">\n {article.excerpt}\n </p>\n )}\n\n {(article.topics ?? []).length > 0 && (\n <div className=\"flex flex-wrap gap-2\">\n {(article.topics ?? []).map((topic) => (\n <span\n key={topic.id}\n className=\"rounded-full border border-[var(--blog-accent-border)] px-2.5 py-1 text-xs font-medium text-[var(--blog-text-accent)]\"\n >\n {topic.name}\n </span>\n ))}\n </div>\n )}\n </div>\n\n <div className=\"text-muted-foreground flex flex-wrap items-center gap-x-3 gap-y-1 text-sm\">\n {article.author && (\n <>\n <AuthorLink author={article.author} basePath={basePath} />\n <span className=\"text-border\">•</span>\n </>\n )}\n <time\n dateTime={article.publishedAt}\n className=\"font-medium\"\n aria-label={`Published ${formattedDate}`}\n >\n {formattedDate}\n </time>\n <span className=\"text-border\">•</span>\n <span className=\"font-medium\">{readingTime}</span>\n </div>\n </div>\n </div>\n </article>\n );\n}\n\nfunction AuthorLink({\n author,\n basePath,\n}: {\n author: PublishedAuthor;\n basePath: string;\n}) {\n return (\n <Link\n href={buildAuthorPath(basePath, author.slug)}\n className=\"inline-flex items-center gap-2 font-medium transition-colors hover:text-[var(--blog-accent)] hover:no-underline\"\n >\n <AuthorAvatar author={author} size=\"sm\" />\n {author.name}\n </Link>\n );\n}\n\nfunction AuthorAvatar({\n author,\n size,\n}: {\n author: PublishedAuthor;\n size: \"sm\" | \"md\";\n}) {\n const sizeClass = size === \"md\" ? \"h-9 w-9 text-sm\" : \"h-6 w-6 text-xs\";\n const initials = getAuthorInitials(author.name);\n\n if (author.avatarUrl) {\n return (\n <Image\n src={author.avatarUrl}\n alt={author.name}\n width={size === \"md\" ? 36 : 24}\n height={size === \"md\" ? 36 : 24}\n className={cn(\"shrink-0 rounded-full object-cover\", sizeClass)}\n loading=\"lazy\"\n />\n );\n }\n\n return (\n <span\n className={cn(\n \"bg-muted inline-flex shrink-0 items-center justify-center rounded-full font-medium\",\n sizeClass,\n )}\n aria-hidden=\"true\"\n >\n {initials}\n </span>\n );\n}\n\nfunction getAuthorInitials(name: string): string {\n const initials = name\n .trim()\n .split(/\\s+/)\n .filter(Boolean)\n .slice(0, 2)\n .map((part) => part[0]?.toUpperCase())\n .join(\"\");\n\n return initials || \"?\";\n}\n\n/**\n * Generate metadata for the blog home page for SEO optimization.\n * This function should be used in the Next.js metadata API.\n */\nexport function generateBlogHomeMetadata(\n siteName?: string,\n siteDescription?: string,\n siteUrl?: string,\n pagination?: {\n currentPage: number;\n totalPages: number;\n },\n basePath = \"/blog\",\n) {\n const baseTitle = siteName ? `${siteName} - Blog` : \"Blog\";\n const title =\n pagination && pagination.currentPage > 1\n ? `${baseTitle} - Page ${pagination.currentPage}`\n : baseTitle;\n\n const description =\n siteDescription ?? \"Read our latest articles and insights.\";\n\n // Generate pagination URLs for SEO\n const baseUrl = normalizeBlogBasePath(basePath) || \"/\";\n const canonicalUrl = siteUrl\n ? `${siteUrl}${pagination && pagination.currentPage > 1 ? `${baseUrl}?page=${pagination.currentPage}` : baseUrl}`\n : undefined;\n\n const prevUrl =\n pagination && pagination.currentPage > 1\n ? siteUrl\n ? `${siteUrl}${pagination.currentPage === 2 ? baseUrl : `${baseUrl}?page=${pagination.currentPage - 1}`}`\n : undefined\n : undefined;\n\n const nextUrl =\n pagination && pagination.currentPage < pagination.totalPages\n ? siteUrl\n ? `${siteUrl}${baseUrl}?page=${pagination.currentPage + 1}`\n : undefined\n : undefined;\n\n return {\n title,\n description,\n openGraph: {\n title,\n description,\n type: \"website\",\n ...(siteUrl && { url: canonicalUrl }),\n },\n twitter: {\n card: \"summary_large_image\",\n title,\n description,\n },\n alternates: {\n ...(canonicalUrl && { canonical: canonicalUrl }),\n },\n other: {\n ...(prevUrl && { prev: prevUrl }),\n ...(nextUrl && { next: nextUrl }),\n },\n };\n}\n","import * as React from \"react\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"../../lib/utils\"\n\nconst badgeVariants = cva(\n \"inline-flex items-center rounded-md border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2\",\n {\n variants: {\n variant: {\n default:\n \"border-transparent bg-primary text-primary-foreground shadow hover:bg-primary/80\",\n secondary:\n \"border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80\",\n destructive:\n \"border-transparent bg-destructive text-destructive-foreground shadow hover:bg-destructive/80\",\n outline: \"text-foreground\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n },\n }\n)\n\nexport interface BadgeProps\n extends React.HTMLAttributes<HTMLDivElement>,\n VariantProps<typeof badgeVariants> {}\n\nfunction Badge({ className, variant, ...props }: BadgeProps) {\n return (\n <div className={cn(badgeVariants({ variant }), className)} {...props} />\n )\n}\n\nexport { Badge, badgeVariants }","import * as React from \"react\"\n\nimport { cn } from \"../../lib/utils\"\n\nfunction Card({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card\"\n className={cn(\n \"bg-card text-card-foreground flex flex-col gap-6 rounded-xl border py-6 shadow-sm\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-header\"\n className={cn(\n \"@container/card-header grid auto-rows-min grid-rows-[auto_auto] items-start gap-1.5 px-6 has-data-[slot=card-action]:grid-cols-[1fr_auto] [.border-b]:pb-6\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardTitle({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-title\"\n className={cn(\"leading-none font-semibold\", className)}\n {...props}\n />\n )\n}\n\nfunction CardDescription({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-description\"\n className={cn(\"text-muted-foreground text-sm\", className)}\n {...props}\n />\n )\n}\n\nfunction CardAction({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-action\"\n className={cn(\n \"col-start-2 row-span-2 row-start-1 self-start justify-self-end\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardContent({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-content\"\n className={cn(\"px-6\", className)}\n {...props}\n />\n )\n}\n\nfunction CardFooter({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-footer\"\n className={cn(\"flex items-center px-6 [.border-t]:pt-6\", className)}\n {...props}\n />\n )\n}\n\nexport {\n Card,\n CardHeader,\n CardFooter,\n CardTitle,\n CardAction,\n CardDescription,\n CardContent,\n}\n","\"use client\";\n\nimport React from \"react\";\nimport { Check, Copy, Share2 } from \"lucide-react\";\n\nimport { cn } from \"../lib/utils\";\n\ntype ClipboardLike = Pick<Clipboard, \"writeText\">;\n\ninterface CopyFallbackDocument {\n body: Pick<HTMLElement, \"appendChild\">;\n createElement: (tagName: \"textarea\") => HTMLTextAreaElement;\n execCommand: (commandId: \"copy\") => boolean;\n}\n\ninterface NavigatorLike {\n clipboard?: ClipboardLike;\n share?: (data: ShareData) => Promise<void>;\n}\n\ninterface ArticleTopActionsProps {\n title: string;\n url: string;\n className?: string;\n size?: \"sm\" | \"md\";\n}\n\nexport function resolveShareUrl(url: string, currentHref?: string): string {\n try {\n return new URL(url).href;\n } catch {\n if (!currentHref) return url;\n }\n\n try {\n return new URL(url, currentHref).href;\n } catch {\n return url;\n }\n}\n\nexport async function copyArticleLink(\n url: string,\n clipboard: ClipboardLike | undefined = globalThis.navigator?.clipboard,\n fallbackDocument: CopyFallbackDocument | undefined =\n typeof document === \"undefined\" ? undefined : document,\n): Promise<void> {\n if (clipboard) {\n try {\n await clipboard.writeText(url);\n return;\n } catch {\n // Fall back below for browser contexts that expose clipboard but deny it.\n }\n }\n\n if (!fallbackDocument) {\n throw new Error(\"Clipboard API is unavailable\");\n }\n\n const textarea = fallbackDocument.createElement(\"textarea\");\n textarea.value = url;\n textarea.setAttribute(\"readonly\", \"\");\n textarea.style.position = \"fixed\";\n textarea.style.left = \"-9999px\";\n\n fallbackDocument.body.appendChild(textarea);\n textarea.select();\n\n try {\n const copied = fallbackDocument.execCommand(\"copy\");\n if (!copied) {\n throw new Error(\"Copy command failed\");\n }\n } finally {\n textarea.remove();\n }\n}\n\nexport async function shareArticle(\n article: { title: string; url: string },\n navigatorLike: NavigatorLike | undefined = globalThis.navigator,\n): Promise<\"shared\" | \"copied\"> {\n if (navigatorLike?.share) {\n await navigatorLike.share({\n title: article.title,\n url: article.url,\n });\n return \"shared\";\n }\n\n await copyArticleLink(article.url, navigatorLike?.clipboard);\n return \"copied\";\n}\n\nexport default function ArticleTopActions({\n title,\n url,\n className,\n size = \"md\",\n}: ArticleTopActionsProps) {\n const [copied, setCopied] = React.useState(false);\n const [sharing, setSharing] = React.useState(false);\n const resolvedUrl = React.useMemo(\n () =>\n resolveShareUrl(\n url,\n typeof window === \"undefined\" ? undefined : window.location.href,\n ),\n [url],\n );\n\n React.useEffect(() => {\n if (!copied) return;\n\n const timeout = window.setTimeout(() => setCopied(false), 2000);\n return () => window.clearTimeout(timeout);\n }, [copied]);\n\n async function handleCopy() {\n await copyArticleLink(resolvedUrl);\n setCopied(true);\n }\n\n async function handleShare() {\n setSharing(true);\n try {\n const result = await shareArticle({ title, url: resolvedUrl });\n if (result === \"copied\") setCopied(true);\n } finally {\n setSharing(false);\n }\n }\n\n const buttonClassName =\n size === \"sm\"\n ? \"h-8 gap-1.5 px-2.5 text-xs\"\n : \"h-9 gap-2 px-3 text-sm\";\n const iconClassName = size === \"sm\" ? \"size-3.5\" : \"size-4\";\n\n return (\n <div\n className={cn(\n \"article-top-actions flex flex-wrap items-center justify-center gap-2\",\n className,\n )}\n >\n <button\n type=\"button\"\n aria-label=\"Copy article link\"\n onClick={handleCopy}\n className={cn(\n \"text-muted-foreground hover:text-foreground border-border inline-flex items-center justify-center rounded-full border font-medium transition-colors hover:border-[var(--blog-accent-border)] hover:bg-[var(--blog-accent-bg)]\",\n buttonClassName,\n )}\n >\n {copied ? (\n <Check className={iconClassName} aria-hidden=\"true\" />\n ) : (\n <Copy className={iconClassName} aria-hidden=\"true\" />\n )}\n <span>{copied ? \"Copied\" : \"Copy link\"}</span>\n </button>\n <button\n type=\"button\"\n aria-label=\"Share article\"\n onClick={handleShare}\n disabled={sharing}\n className={cn(\n \"text-muted-foreground hover:text-foreground border-border inline-flex items-center justify-center rounded-full border font-medium transition-colors hover:border-[var(--blog-accent-border)] hover:bg-[var(--blog-accent-bg)] disabled:cursor-wait disabled:opacity-60\",\n buttonClassName,\n )}\n >\n <Share2 className={iconClassName} aria-hidden=\"true\" />\n <span>Share</span>\n </button>\n </div>\n );\n}\n","/* eslint-disable @next/next/no-img-element */\n\nimport type React from \"react\";\n\nimport { cn } from \"../lib/utils\";\n\ntype ArticleImageProps = React.ImgHTMLAttributes<HTMLImageElement>;\n\nexport function ExpandableArticleImage({\n alt = \"\",\n className,\n src,\n ...props\n}: ArticleImageProps) {\n if (typeof src !== \"string\" || src.length === 0) {\n return <img alt={alt} className={className} {...props} />;\n }\n\n const previewId = `blog-image-preview-${hashImageSrc(src)}`;\n\n return (\n <>\n <a\n href={`#${previewId}`}\n className=\"group mx-auto block cursor-zoom-in rounded-2xl focus-visible:ring-2 focus-visible:ring-[var(--blog-text-accent)] focus-visible:ring-offset-2 focus-visible:outline-none\"\n aria-label={alt ? `Expand image: ${alt}` : \"Expand article image\"}\n >\n <img\n src={src}\n alt={alt}\n className={cn(\n \"mx-auto rounded-2xl border border-[var(--blog-accent-border)] shadow-[0_18px_60px_rgb(168_85_247_/_0.12)] transition-opacity group-hover:opacity-95\",\n className,\n )}\n {...props}\n />\n </a>\n\n <div\n id={previewId}\n className=\"invisible fixed inset-0 z-50 flex opacity-0 transition-opacity target:visible target:opacity-100\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label={alt ? `Image preview: ${alt}` : \"Image preview\"}\n >\n <a\n href=\"#article-content\"\n className=\"absolute inset-0 bg-black/85 backdrop-blur-sm\"\n aria-label=\"Close image preview\"\n />\n <div className=\"pointer-events-none relative z-10 flex min-h-screen w-full items-center justify-center p-4 sm:p-6\">\n <img\n src={src}\n alt={alt}\n className=\"pointer-events-auto h-[88vh] w-[94vw] rounded-3xl object-contain shadow-2xl\"\n />\n </div>\n <a\n href=\"#article-content\"\n className=\"absolute top-4 right-4 z-20 inline-flex size-10 items-center justify-center rounded-full border border-white/20 bg-black/50 text-xl leading-none text-white no-underline transition-colors hover:bg-white/10 focus-visible:ring-2 focus-visible:ring-white focus-visible:outline-none\"\n aria-label=\"Close image preview\"\n >\n ×\n </a>\n </div>\n </>\n );\n}\n\nfunction hashImageSrc(src: string): string {\n let hash = 0;\n\n for (let index = 0; index < src.length; index += 1) {\n hash = (hash << 5) - hash + src.charCodeAt(index);\n hash |= 0;\n }\n\n return Math.abs(hash).toString(36);\n}\n","import {\n formatTableOfContentsSummary,\n getTocItemState,\n type TocItem,\n} from \"../lib/article-ui\";\n\ninterface ArticleReadingProgressProps {\n items: TocItem[];\n contentId: string;\n variant: \"mobile\" | \"desktop\";\n showProgress?: boolean;\n}\n\nexport function ArticleReadingProgress({\n items,\n contentId,\n variant,\n showProgress = true,\n}: ArticleReadingProgressProps) {\n const activeItemId = items[0]?.id ?? null;\n\n return (\n <>\n {showProgress && (\n <div\n data-blog-reading-progress={contentId}\n className=\"fixed inset-x-0 top-0 z-50 h-1 origin-left bg-[var(--blog-accent)] motion-safe:transition-transform\"\n style={{ transform: \"scaleX(0)\" }}\n role=\"progressbar\"\n aria-label=\"Reading progress\"\n aria-valuemin={0}\n aria-valuemax={100}\n aria-valuenow={0}\n suppressHydrationWarning\n />\n )}\n\n <ArticleTableOfContents\n items={items}\n activeItemId={activeItemId}\n variant={variant}\n />\n\n {showProgress && (\n <script\n dangerouslySetInnerHTML={{\n __html: getReadingProgressScript(contentId, items),\n }}\n />\n )}\n </>\n );\n}\n\nfunction ArticleTableOfContents({\n items,\n activeItemId,\n variant,\n}: {\n items: TocItem[];\n activeItemId: string | null;\n variant: \"mobile\" | \"desktop\";\n}) {\n if (items.length === 0) {\n return null;\n }\n\n const list = (\n <ul className=\"space-y-2 text-sm\">\n {items.map((item) => {\n const itemState = getTocItemState(item.id, activeItemId);\n\n return (\n <li key={item.id} className={item.level === 3 ? \"pl-4\" : undefined}>\n <a\n href={`#${item.id}`}\n aria-current={itemState.ariaCurrent}\n data-blog-toc-link={item.id}\n data-active={itemState.isActive ? \"true\" : \"false\"}\n suppressHydrationWarning\n className=\"text-muted-foreground hover:text-[var(--blog-text-accent)] data-[active=true]:border-[var(--blog-accent)] data-[active=true]:text-[var(--blog-text-accent)] block border-l-2 border-transparent pl-3 leading-snug transition-colors\"\n >\n {item.text}\n </a>\n </li>\n );\n })}\n </ul>\n );\n\n if (variant === \"mobile\") {\n return (\n <details className=\"group mb-6 rounded-2xl border border-[var(--blog-accent-border)] bg-[var(--blog-accent-bg)] lg:hidden\">\n <summary className=\"text-foreground flex cursor-pointer list-none items-center justify-between gap-3 px-4 py-3 text-sm font-semibold [&::-webkit-details-marker]:hidden\">\n <span>On this page</span>\n <span className=\"text-muted-foreground flex items-center gap-2 text-xs font-medium\">\n {formatTableOfContentsSummary(items.length)}\n <span\n className=\"text-[var(--blog-text-accent)] transition-transform group-open:rotate-180\"\n aria-hidden=\"true\"\n >\n ↓\n </span>\n </span>\n </summary>\n <nav\n aria-label=\"Table of contents\"\n className=\"border-t border-[var(--blog-accent-border)] px-4 py-4\"\n >\n {list}\n </nav>\n </details>\n );\n }\n\n return (\n <aside className=\"hidden lg:block\">\n <nav\n aria-label=\"Table of contents\"\n className=\"sticky top-24 max-h-[calc(100vh-8rem)] overflow-y-auto border-l border-border pl-5\"\n >\n <p className=\"text-muted-foreground mb-3 text-xs font-semibold tracking-wider uppercase\">\n On this page\n </p>\n {list}\n </nav>\n </aside>\n );\n}\n\nfunction getReadingProgressScript(contentId: string, items: TocItem[]): string {\n return `\n(() => {\n const contentId = ${JSON.stringify(contentId)};\n const itemIds = ${JSON.stringify(items.map((item) => item.id))};\n const progressElement = document.querySelector('[data-blog-reading-progress=\"' + contentId + '\"]');\n let animationFrameId = 0;\n let pendingHashItemId = decodeURIComponent(window.location.hash.replace(/^#/, ''));\n\n const normalizeProgress = (value) => {\n if (!Number.isFinite(value)) return 0;\n return Math.min(100, Math.max(0, value));\n };\n\n const setActiveItem = (activeItemId) => {\n const tocLinks = Array.from(document.querySelectorAll('[data-blog-toc-link]'));\n\n for (const link of tocLinks) {\n const isActive = link.getAttribute('data-blog-toc-link') === activeItemId;\n link.setAttribute('data-active', isActive ? 'true' : 'false');\n if (isActive) {\n link.setAttribute('aria-current', 'location');\n } else {\n link.removeAttribute('aria-current');\n }\n }\n };\n\n const updateScrollState = () => {\n const contentElement = document.getElementById(contentId);\n if (!contentElement) return;\n\n const contentRect = contentElement.getBoundingClientRect();\n const scrollTop = window.scrollY;\n const contentTop = contentRect.top + scrollTop;\n const readableDistance = contentElement.offsetHeight - window.innerHeight;\n const nextProgress = readableDistance <= 0\n ? scrollTop >= contentTop ? 100 : 0\n : ((scrollTop - contentTop) / readableDistance) * 100;\n const progress = normalizeProgress(nextProgress);\n\n if (progressElement) {\n progressElement.style.transform = 'scaleX(' + progress / 100 + ')';\n progressElement.setAttribute('aria-valuenow', String(Math.round(progress)));\n }\n\n const headings = itemIds\n .map((id) => document.getElementById(id))\n .filter(Boolean);\n if (pendingHashItemId && itemIds.includes(pendingHashItemId)) {\n setActiveItem(pendingHashItemId);\n pendingHashItemId = '';\n return;\n }\n\n const activeOffset = Math.max(160, Math.round(window.innerHeight * 0.33));\n const activeHeading = headings\n .filter((heading) => heading.getBoundingClientRect().top <= activeOffset)\n .at(-1) || headings[0] || null;\n\n setActiveItem(activeHeading ? activeHeading.id : null);\n };\n\n const scheduleUpdate = () => {\n window.cancelAnimationFrame(animationFrameId);\n animationFrameId = window.requestAnimationFrame(updateScrollState);\n };\n\n scheduleUpdate();\n window.addEventListener('scroll', scheduleUpdate, { passive: true });\n window.addEventListener('resize', scheduleUpdate);\n window.addEventListener('hashchange', () => {\n pendingHashItemId = decodeURIComponent(window.location.hash.replace(/^#/, ''));\n scheduleUpdate();\n });\n})();\n`;\n}\n","import * as React from \"react\"\nimport * as SeparatorPrimitive from \"@radix-ui/react-separator\"\n\nimport { cn } from \"../../lib/utils\"\n\nconst Separator = React.forwardRef<\n React.ElementRef<typeof SeparatorPrimitive.Root>,\n React.ComponentPropsWithoutRef<typeof SeparatorPrimitive.Root>\n>(\n (\n { className, orientation = \"horizontal\", decorative = true, ...props },\n ref\n ) => (\n <SeparatorPrimitive.Root\n ref={ref}\n decorative={decorative}\n orientation={orientation}\n className={cn(\n \"shrink-0 bg-border\",\n orientation === \"horizontal\" ? \"h-[1px] w-full\" : \"h-full w-[1px]\",\n className\n )}\n {...props}\n />\n )\n)\nSeparator.displayName = SeparatorPrimitive.Root.displayName\n\nexport { Separator }","import remarkGfm from \"remark-gfm\";\nimport remarkToc from \"remark-toc\";\nimport rehypeSlug from \"rehype-slug\";\n\ninterface HastNode {\n type?: string;\n tagName?: string;\n value?: string;\n children?: HastNode[];\n}\n\nexport const articleMdxOptions = {\n mdxOptions: {\n remarkPlugins: [remarkToc, remarkGfm],\n rehypePlugins: [rehypeUnwrapStandaloneImages, rehypeSlug],\n },\n};\n\nexport function rehypeUnwrapStandaloneImages() {\n return (tree: HastNode) => {\n unwrapStandaloneImages(tree);\n };\n}\n\nfunction unwrapStandaloneImages(node: HastNode) {\n if (!node.children) {\n return;\n }\n\n node.children = node.children.flatMap((child) => {\n unwrapStandaloneImages(child);\n\n if (isStandaloneImageParagraph(child)) {\n return child.children?.filter(isMeaningfulNode) ?? [child];\n }\n\n return [child];\n });\n}\n\nfunction isStandaloneImageParagraph(node: HastNode): boolean {\n if (node.type !== \"element\" || node.tagName !== \"p\" || !node.children) {\n return false;\n }\n\n const meaningfulChildren = node.children.filter(isMeaningfulNode);\n return (\n meaningfulChildren.length === 1 && isImageLikeNode(meaningfulChildren[0])\n );\n}\n\nfunction isImageLikeNode(node: HastNode | undefined): boolean {\n if (node?.type !== \"element\") {\n return false;\n }\n\n if (node.tagName === \"img\") {\n return true;\n }\n\n if (node.tagName !== \"a\" || !node.children) {\n return false;\n }\n\n const meaningfulChildren = node.children.filter(isMeaningfulNode);\n return (\n meaningfulChildren.length === 1 && meaningfulChildren[0]?.tagName === \"img\"\n );\n}\n\nfunction isMeaningfulNode(node: HastNode): boolean {\n return node.type !== \"text\" || Boolean(node.value?.trim());\n}\n","import React from \"react\";\nimport Image from \"next/image\";\nimport Link from \"next/link\";\nimport { MDXRemote } from \"next-mdx-remote-client/rsc\";\nimport {\n type PublishedArticle,\n type PublishedAuthor,\n type PublishedNewsletterSettings,\n} from \"../../../types/contracts\";\nimport { cn } from \"../../../lib/utils\";\nimport { ArrowLeft, ArrowUpRight, Globe, Mail } from \"lucide-react\";\nimport { FaGithub, FaLinkedinIn, FaXTwitter } from \"react-icons/fa6\";\nimport { Badge } from \"../../../components/ui/badge\";\nimport { Card, CardContent } from \"../../../components/ui/card\";\nimport ArticleTopActions from \"../../../components/ArticleTopActions\";\nimport { ExpandableArticleImage } from \"../../../components/ExpandableArticleImage\";\nimport { ArticleReadingProgress } from \"../../../components/ArticleReadingProgress\";\nimport { Separator } from \"../../../components/ui/separator\";\nimport {\n generateCompleteArticleStructuredData,\n createStructuredDataScript,\n} from \"../../../lib/structured-data\";\nimport { articleMdxOptions } from \"../../../lib/mdx\";\nimport {\n buildAuthorPath,\n buildBlogPath,\n normalizeBlogBasePath,\n} from \"../../../lib/urls\";\nimport { NewsletterSignup } from \"../../../components/NewsletterSignup\";\nimport {\n type BlogTheme,\n extractTableOfContents,\n formatArticleDateMeta,\n getBlogThemeStyle,\n} from \"../../../lib/article-ui\";\n\nexport interface ArticlePageProps {\n article: PublishedArticle;\n className?: string;\n /** Optional navigation links */\n navigation?: {\n backToHome?: {\n url: string;\n label?: string;\n };\n previousArticle?: {\n url: string;\n title: string;\n featuredImage?: string;\n featuredImageAlt?: string;\n };\n nextArticle?: {\n url: string;\n title: string;\n featuredImage?: string;\n featuredImageAlt?: string;\n };\n };\n /** Public path where this blog is mounted, e.g. \"/blog\" or \"/new-blog\". */\n basePath?: string;\n /** Optional theme values for host-site brand integration. */\n theme?: BlogTheme;\n /** Optional post-article CTA supplied by the host site. */\n postArticleCta?: {\n title: string;\n description?: string;\n href: string;\n label: string;\n };\n /** Optional Bloggy-owned newsletter capture configuration. */\n newsletter?: PublishedNewsletterSettings;\n /** Render interactive preview success without persisting subscribers. */\n newsletterPreviewMode?: boolean;\n /** Optional related articles supplied by the host site. */\n relatedArticles?: PublishedArticle[];\n /** Whether to render static article share links. */\n showShareLinks?: boolean;\n}\n\n/**\n * Individual article page component that displays full article content.\n *\n * This component is designed to be used by customers who install the\n * @xexr/blog-platform package. It provides a complete article view\n * with proper SEO metadata, structured data, and accessibility features.\n */\n/**\n * Helper function to format reading time in minutes\n */\nfunction formatReadingTime(seconds: number): string {\n const minutes = Math.ceil(seconds / 60);\n return `${minutes} min read`;\n}\n\nfunction formatCreditUrl(url: string): string {\n try {\n return new URL(url).hostname.replace(/^www\\./, \"\");\n } catch {\n return url;\n }\n}\n\nfunction FeaturedImageCredit({\n creditText,\n creditUrl,\n}: {\n creditText?: string;\n creditUrl?: string;\n}) {\n if (!creditText && !creditUrl) {\n return null;\n }\n\n const label = creditText ?? formatCreditUrl(creditUrl ?? \"\");\n\n return (\n <span>\n Credit:{\" \"}\n {creditUrl ? (\n <a\n href={creditUrl}\n target=\"_blank\"\n rel=\"noreferrer\"\n className=\"underline underline-offset-2 transition-colors hover:text-[var(--blog-text-accent)]\"\n >\n {label}\n </a>\n ) : (\n label\n )}\n </span>\n );\n}\n\nexport default function ArticlePage({\n article,\n className,\n navigation,\n basePath = \"/blog\",\n theme,\n postArticleCta,\n newsletter,\n newsletterPreviewMode = false,\n relatedArticles = [],\n showShareLinks = true,\n}: ArticlePageProps) {\n const normalizedBasePath = normalizeBlogBasePath(basePath) || \"/\";\n const dateMeta = formatArticleDateMeta(\n article.publishedAt,\n article.updatedAt,\n );\n const readingTime = formatReadingTime(article.readingSeconds);\n const tocItems = extractTableOfContents(article.content);\n const articleUrl =\n article.meta.canonicalUrl ??\n buildBlogPath(normalizedBasePath, article.slug);\n const newsletterSettings = newsletter ?? article.site.newsletter;\n\n // Use the featured image URL provided by Bloggy (hosted on Bloggy's domain)\n const imageUrl = article.featuredImage;\n const hasFeaturedImageMeta = Boolean(\n article.featuredImageCaption ??\n article.featuredImageCreditText ??\n article.featuredImageCreditUrl,\n );\n\n return (\n <article\n style={getBlogThemeStyle(theme)}\n className={cn(\n \"article-page mx-auto max-w-6xl px-4 py-6 pb-12 sm:px-6 sm:py-8 sm:pb-16 lg:px-8 lg:py-12 lg:pb-24\",\n className,\n )}\n >\n {/* Navigation */}\n {navigation?.backToHome && (\n <header className=\"mx-auto mb-8 max-w-4xl sm:mb-12 lg:mb-16\">\n <Link\n href={navigation.backToHome.url}\n className=\"text-muted-foreground group focus-visible:ring-ring inline-flex touch-manipulation items-center space-x-2 rounded-md px-2 py-1 transition-colors hover:text-[var(--blog-accent)] focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-none sm:space-x-3\"\n aria-label={navigation.backToHome.label ?? \"Return to blog\"}\n >\n <ArrowLeft\n className=\"h-4 w-4 transition-transform group-hover:-translate-x-1 sm:h-5 sm:w-5\"\n aria-hidden=\"true\"\n />\n <span className=\"text-sm font-medium sm:text-base\">\n <span className=\"hidden sm:inline\">\n {navigation.backToHome.label ?? \"Back to all articles\"}\n </span>\n <span className=\"sm:hidden\">Back</span>\n </span>\n </Link>\n </header>\n )}\n\n <style>{`\n .article-content figure > p {\n margin-top: 0 !important;\n margin-bottom: 0 !important;\n }\n\n .article-content figure figcaption {\n margin-top: 0.5rem !important;\n text-align: center;\n font-size: 0.875rem !important;\n line-height: 1.35 !important;\n color: hsl(var(--muted-foreground));\n }\n\n .article-content figure figcaption .blog-image-credit {\n display: block;\n margin-top: 0.25rem;\n font-size: 0.75rem;\n line-height: 1.25;\n letter-spacing: 0.025em;\n opacity: 0.8;\n }\n\n .article-content figure figcaption > span:not(.blog-image-credit) {\n margin-left: 0.5rem;\n padding-left: 0.5rem;\n border-left: 1px solid var(--blog-accent-border);\n font-size: 0.75rem;\n letter-spacing: 0.025em;\n opacity: 0.8;\n }\n\n .article-content figure figcaption a {\n color: inherit;\n text-decoration-line: underline;\n text-underline-offset: 0.18em;\n }\n `}</style>\n\n {/* Article Header */}\n <header className=\"article-header mx-auto mb-6 max-w-4xl space-y-4 text-center sm:mb-8 sm:space-y-6 lg:mb-12 lg:space-y-8\">\n {/* Title */}\n <h1 className=\"article-title bg-linear-to-br from-[var(--blog-accent-hover)] via-[var(--blog-text-accent)] to-fuchsia-200 bg-clip-text px-4 text-2xl leading-tight font-light tracking-tight text-balance text-transparent sm:px-0 sm:text-3xl md:text-4xl lg:text-5xl xl:text-6xl\">\n {article.title}\n </h1>\n\n {/* Excerpt */}\n {article.excerpt && (\n <p className=\"article-excerpt text-muted-foreground mx-auto mt-6 max-w-[42rem] px-4 text-lg leading-relaxed text-balance sm:mt-8 sm:max-w-[46rem] sm:px-0 sm:text-xl md:max-w-[52rem] md:text-2xl lg:max-w-4xl lg:text-2xl\">\n {article.excerpt}\n </p>\n )}\n\n {/* Article Metadata */}\n <div className=\"article-meta text-muted-foreground flex flex-col items-center gap-2 text-sm sm:gap-3 sm:text-base\">\n {article.author && (\n <div className=\"flex items-center gap-2\">\n <span className=\"sr-only\">Author</span>\n <Link\n href={buildAuthorPath(normalizedBasePath, article.author.slug)}\n className=\"inline-flex items-center gap-2 font-medium transition-colors hover:text-[var(--blog-accent)] hover:no-underline\"\n >\n <AuthorAvatar author={article.author} size=\"md\" />\n {article.author.name}\n </Link>\n {article.author.isGuest && (\n <Badge variant=\"outline\" className=\"text-xs\">\n Guest Author\n </Badge>\n )}\n </div>\n )}\n\n <div className=\"flex flex-wrap items-center justify-center gap-x-3 gap-y-1\">\n <time\n dateTime={article.publishedAt}\n className=\"font-medium\"\n aria-label={`Published ${dateMeta.publishedDateLabel}`}\n >\n Published {dateMeta.publishedDateLabel}\n </time>\n <span className=\"text-border\">•</span>\n <span className=\"font-medium\">\n {dateMeta.publishedRelativeLabel}\n </span>\n <span className=\"text-border\">•</span>\n <span className=\"font-medium\">{readingTime}</span>\n </div>\n\n {dateMeta.isUpdated && (\n <time dateTime={article.updatedAt} className=\"text-xs\">\n Updated {dateMeta.updatedDateLabel}\n </time>\n )}\n\n {showShareLinks && (\n <ArticleTopActions\n title={article.title}\n url={articleUrl}\n size=\"sm\"\n />\n )}\n\n <div className=\"bg-border h-px w-6 sm:w-8\" aria-hidden=\"true\"></div>\n\n {(article.topics ?? []).length > 0 ? (\n <nav\n aria-label=\"Article topics\"\n className=\"flex flex-wrap justify-center gap-2\"\n >\n {(article.topics ?? []).map((topic) => (\n <Link\n key={topic.id}\n href={buildBlogPath(\n (navigation?.backToHome?.url ?? \"/blog\").replace(/\\/$/, \"\"),\n `topics/${topic.slug}`,\n )}\n className=\"rounded-full border border-[var(--blog-accent-border)] bg-[var(--blog-accent-bg)] px-3 py-1 text-xs font-medium text-[var(--blog-text-accent)] transition-colors hover:border-[var(--blog-text-accent)] hover:text-[var(--blog-text-accent-hover)]\"\n >\n {topic.name}\n </Link>\n ))}\n </nav>\n ) : (\n <span\n className=\"text-xs tracking-wider uppercase sm:text-sm\"\n role=\"text\"\n >\n From {article.site.name}\n </span>\n )}\n </div>\n </header>\n\n {/* Featured Image */}\n {imageUrl && (\n <figure className=\"article-featured-image mx-auto my-8 w-full max-w-4xl sm:my-12 lg:my-16\">\n <div className=\"aspect-[16/9] overflow-hidden rounded-3xl border border-[var(--blog-accent-border)] shadow-[0_24px_80px_rgb(168_85_247_/_0.14)]\">\n <Image\n src={imageUrl}\n alt={\n article.featuredImageAlt ??\n `Featured image for ${article.title}`\n }\n className=\"h-full w-full object-cover\"\n width={800}\n height={450}\n priority\n />\n </div>\n\n {hasFeaturedImageMeta && (\n <figcaption className=\"text-muted-foreground mt-3 space-y-1 px-2 text-center text-sm leading-relaxed sm:px-0\">\n {article.featuredImageCaption && (\n <p>{article.featuredImageCaption}</p>\n )}\n {(article.featuredImageCreditText ??\n article.featuredImageCreditUrl) && (\n <p className=\"text-xs\">\n <FeaturedImageCredit\n creditText={article.featuredImageCreditText}\n creditUrl={article.featuredImageCreditUrl}\n />\n </p>\n )}\n </figcaption>\n )}\n </figure>\n )}\n\n {/* Article Content */}\n <div\n id=\"article-content\"\n className=\"article-content mx-auto grid max-w-6xl grid-cols-1 gap-8 lg:grid-cols-[minmax(0,1fr)_14rem] lg:gap-12\"\n >\n <div className=\"min-w-0\">\n <ArticleReadingProgress\n items={tocItems}\n contentId=\"article-body\"\n variant=\"mobile\"\n />\n\n <div\n id=\"article-body\"\n className=\"prose prose-sm sm:prose-base lg:prose-lg xl:prose-xl prose-gray dark:prose-invert prose-headings:scroll-mt-20 prose-headings:font-light prose-headings:text-balance prose-headings:text-[var(--blog-text-accent)] prose-h1:text-2xl sm:prose-h1:text-3xl lg:prose-h1:text-4xl prose-h2:text-xl sm:prose-h2:text-2xl lg:prose-h2:text-3xl prose-h3:text-lg sm:prose-h3:text-xl lg:prose-h3:text-2xl prose-p:leading-relaxed prose-p:text-pretty prose-a:text-[var(--blog-text-accent)] prose-a:transition-colors hover:prose-a:text-[var(--blog-text-accent-hover)] [&_figure>p]:!my-0 [&_figcaption]:!mt-2 [&_figcaption]:text-center [&_figcaption]:!text-sm [&_figcaption]:!leading-snug [&_figcaption]:text-muted-foreground [&_figcaption_.blog-image-credit]:mt-1 [&_figcaption_.blog-image-credit]:block [&_figcaption_.blog-image-credit]:text-xs [&_figcaption_.blog-image-credit]:tracking-wide [&_figcaption_.blog-image-credit]:text-muted-foreground/80 [&_figcaption>span:not(.blog-image-credit)]:ml-2 [&_figcaption>span:not(.blog-image-credit)]:border-l [&_figcaption>span:not(.blog-image-credit)]:border-[var(--blog-accent-border)] [&_figcaption>span:not(.blog-image-credit)]:pl-2 [&_figcaption>span:not(.blog-image-credit)]:text-xs [&_figcaption>span:not(.blog-image-credit)]:tracking-wide [&_figcaption>span:not(.blog-image-credit)]:text-muted-foreground/80 max-w-none\"\n >\n <MDXRemote\n source={article.content}\n options={articleMdxOptions}\n components={{ img: ExpandableArticleImage }}\n />\n </div>\n </div>\n\n <ArticleReadingProgress\n items={tocItems}\n contentId=\"article-body\"\n variant=\"desktop\"\n showProgress={false}\n />\n </div>\n\n {/* Author Bio */}\n {article.author?.bio && (\n <div id=\"about-author\" className=\"author-bio mx-auto mt-12 max-w-4xl\">\n <Separator className=\"mb-8\" />\n <Card className=\"border-[var(--blog-accent-border)] bg-[var(--blog-accent-bg)]\">\n <CardContent className=\"flex flex-col gap-4 p-5 sm:flex-row sm:items-start sm:p-6\">\n <div className=\"shrink-0\">\n <AuthorAvatar author={article.author} size=\"lg\" />\n </div>\n <div className=\"min-w-0 flex-1 space-y-2\">\n <div className=\"flex flex-col gap-2 sm:flex-row sm:items-start sm:justify-between\">\n <div className=\"min-w-0\">\n <p className=\"text-muted-foreground text-sm font-medium\">\n Written by\n </p>\n <h2 className=\"text-foreground flex flex-wrap items-center gap-2 text-xl font-semibold\">\n <Link\n href={buildAuthorPath(\n normalizedBasePath,\n article.author.slug,\n )}\n className=\"transition-colors hover:text-[var(--blog-accent)] hover:no-underline\"\n >\n {article.author.name}\n </Link>\n {article.author.isGuest && (\n <Badge variant=\"outline\" className=\"text-xs\">\n Guest Author\n </Badge>\n )}\n </h2>\n </div>\n <AuthorSocialLinks author={article.author} />\n </div>\n <p className=\"text-muted-foreground leading-relaxed\">\n {article.author.bio}\n </p>\n </div>\n </CardContent>\n </Card>\n </div>\n )}\n\n {((postArticleCta ?? false) ||\n (newsletterSettings?.enabled ?? false) ||\n showShareLinks ||\n relatedArticles.length > 0) && (\n <div className=\"mx-auto mt-12 max-w-4xl space-y-8\">\n <Separator />\n {postArticleCta && <PostArticleCta cta={postArticleCta} />}\n {newsletterSettings?.enabled && (\n <NewsletterSignup\n siteId={article.site.id}\n settings={newsletterSettings}\n sourceSurface=\"article\"\n sourceArticleSlug={article.slug}\n sourceUrl={articleUrl}\n previewMode={newsletterPreviewMode}\n />\n )}\n {showShareLinks && (\n <ArticleShareLinks title={article.title} url={articleUrl} />\n )}\n {relatedArticles.length > 0 && (\n <RelatedArticles\n articles={relatedArticles.slice(0, 3)}\n basePath={normalizedBasePath}\n />\n )}\n </div>\n )}\n\n {/* Article Navigation */}\n {(Boolean(navigation?.previousArticle) ||\n Boolean(navigation?.nextArticle)) && (\n <nav className=\"article-nav mx-auto mt-12 max-w-4xl\">\n <Separator className=\"mb-8\" />\n <div className=\"grid grid-cols-1 gap-4 md:grid-cols-2\">\n {navigation?.previousArticle && (\n <Card className=\"group cursor-pointer transition-colors hover:border-[var(--blog-accent-border)] hover:bg-[var(--blog-accent-bg)]\">\n <Link href={navigation.previousArticle.url} className=\"block\">\n {navigation.previousArticle.featuredImage && (\n <ArticleCardImage\n src={navigation.previousArticle.featuredImage}\n alt={\n navigation.previousArticle.featuredImageAlt ??\n `Featured image for ${navigation.previousArticle.title}`\n }\n />\n )}\n <CardContent className=\"p-4\">\n <div className=\"text-muted-foreground mb-2 text-sm font-medium\">\n ← Previous Article\n </div>\n <div className=\"text-foreground transition-colors group-hover:text-[var(--blog-text-accent)]\">\n {navigation.previousArticle.title}\n </div>\n </CardContent>\n </Link>\n </Card>\n )}\n {navigation?.nextArticle && (\n <Card\n className={cn(\n \"group cursor-pointer transition-colors hover:border-[var(--blog-accent-border)] hover:bg-[var(--blog-accent-bg)]\",\n !navigation?.previousArticle && \"md:col-start-2\",\n )}\n >\n <Link href={navigation.nextArticle.url} className=\"block\">\n {navigation.nextArticle.featuredImage && (\n <ArticleCardImage\n src={navigation.nextArticle.featuredImage}\n alt={\n navigation.nextArticle.featuredImageAlt ??\n `Featured image for ${navigation.nextArticle.title}`\n }\n />\n )}\n <CardContent className=\"p-4 md:text-right\">\n <div className=\"text-muted-foreground mb-2 text-sm font-medium\">\n Next Article →\n </div>\n <div className=\"text-foreground transition-colors group-hover:text-[var(--blog-text-accent)]\">\n {navigation.nextArticle.title}\n </div>\n </CardContent>\n </Link>\n </Card>\n )}\n </div>\n </nav>\n )}\n\n {/* JSON-LD Structured Data */}\n {(() => {\n const structuredDataProps = createStructuredDataScript(\n generateCompleteArticleStructuredData(article, {\n pathPrefix: normalizedBasePath,\n }),\n );\n return (\n <script\n type={structuredDataProps.type}\n dangerouslySetInnerHTML={\n structuredDataProps.dangerouslySetInnerHTML\n }\n />\n );\n })()}\n </article>\n );\n}\n\nfunction AuthorAvatar({\n author,\n size,\n}: {\n author: PublishedAuthor;\n size: \"md\" | \"lg\";\n}) {\n const sizeClass = size === \"lg\" ? \"h-12 w-12 text-base\" : \"h-9 w-9 text-sm\";\n const initials = getAuthorInitials(author.name);\n\n if (author.avatarUrl) {\n return (\n <Image\n src={author.avatarUrl}\n alt={author.name}\n width={size === \"lg\" ? 48 : 36}\n height={size === \"lg\" ? 48 : 36}\n className={cn(\"shrink-0 rounded-full object-cover\", sizeClass)}\n loading=\"lazy\"\n />\n );\n }\n\n return (\n <span\n className={cn(\n \"bg-muted text-muted-foreground inline-flex shrink-0 items-center justify-center rounded-full font-medium\",\n sizeClass,\n )}\n aria-hidden=\"true\"\n >\n {initials}\n </span>\n );\n}\n\ninterface AuthorSocialLinkView {\n key: string;\n href: string;\n label: string;\n external: boolean;\n icon: React.ReactNode;\n}\n\nfunction AuthorSocialLinks({ author }: { author: PublishedAuthor }) {\n const links = getAuthorSocialLinks(author);\n if (links.length === 0) return null;\n\n return (\n <div className=\"flex flex-wrap items-center gap-1 sm:justify-end\">\n {links.map((link) => (\n <a\n key={link.key}\n href={link.href}\n target={link.external ? \"_blank\" : undefined}\n rel={link.external ? \"noopener noreferrer\" : undefined}\n aria-label={`${author.name} ${link.label}`}\n className=\"text-muted-foreground hover:bg-background/60 hover:text-foreground inline-flex size-7 items-center justify-center rounded-full transition-colors\"\n >\n {link.icon}\n </a>\n ))}\n </div>\n );\n}\n\nfunction getAuthorSocialLinks(author: PublishedAuthor): AuthorSocialLinkView[] {\n const links = author.socialLinks;\n if (!links) return [];\n\n const socialLinks: Array<AuthorSocialLinkView | false | undefined> = [\n links.website\n ? {\n key: \"website\",\n href: links.website,\n label: \"website\",\n external: true,\n icon: <Globe className=\"size-4\" aria-hidden=\"true\" />,\n }\n : undefined,\n links.x\n ? {\n key: \"x\",\n href: links.x,\n label: \"on X\",\n external: true,\n icon: <FaXTwitter className=\"size-4\" aria-hidden=\"true\" />,\n }\n : undefined,\n links.linkedin\n ? {\n key: \"linkedin\",\n href: links.linkedin,\n label: \"on LinkedIn\",\n external: true,\n icon: <FaLinkedinIn className=\"size-4\" aria-hidden=\"true\" />,\n }\n : undefined,\n links.github\n ? {\n key: \"github\",\n href: links.github,\n label: \"on GitHub\",\n external: true,\n icon: <FaGithub className=\"size-4\" aria-hidden=\"true\" />,\n }\n : undefined,\n links.email\n ? {\n key: \"email\",\n href: `mailto:${links.email}`,\n label: \"email\",\n external: false,\n icon: <Mail className=\"size-4\" aria-hidden=\"true\" />,\n }\n : undefined,\n ];\n\n return socialLinks.filter((link): link is AuthorSocialLinkView =>\n Boolean(link),\n );\n}\n\nfunction getAuthorInitials(name: string): string {\n const initials = name\n .trim()\n .split(/\\s+/)\n .filter(Boolean)\n .slice(0, 2)\n .map((part) => part[0]?.toUpperCase())\n .join(\"\");\n\n return initials || \"?\";\n}\n\nfunction PostArticleCta({\n cta,\n}: {\n cta: NonNullable<ArticlePageProps[\"postArticleCta\"]>;\n}) {\n return (\n <div className=\"rounded-2xl border border-[var(--blog-accent-border)] bg-[var(--blog-accent-bg)] p-5 sm:p-6\">\n <div className=\"flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between\">\n <div className=\"space-y-1\">\n <h2 className=\"text-foreground text-xl font-semibold\">{cta.title}</h2>\n {cta.description && (\n <p className=\"text-muted-foreground leading-relaxed\">\n {cta.description}\n </p>\n )}\n </div>\n <Link\n href={cta.href}\n className=\"inline-flex shrink-0 items-center justify-center gap-2 rounded-full bg-[var(--blog-accent)] px-4 py-2 text-sm font-semibold text-white transition-opacity hover:opacity-90\"\n >\n {cta.label}\n <ArrowUpRight className=\"size-4\" aria-hidden=\"true\" />\n </Link>\n </div>\n </div>\n );\n}\n\nfunction ArticleShareLinks({ title, url }: { title: string; url: string }) {\n const encodedTitle = encodeURIComponent(title);\n const encodedUrl = encodeURIComponent(url);\n\n return (\n <div className=\"flex flex-wrap items-center justify-center gap-2 sm:gap-3\">\n <ArticleTopActions title={title} url={url} size=\"sm\" />\n <a\n href={`https://x.com/intent/tweet?text=${encodedTitle}&url=${encodedUrl}`}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n aria-label=\"Share on X\"\n className=\"text-muted-foreground hover:text-foreground border-border inline-flex size-9 items-center justify-center rounded-full border grayscale transition-colors hover:border-[var(--blog-accent-border)] hover:bg-[var(--blog-accent-bg)]\"\n >\n <FaXTwitter className=\"size-4\" aria-hidden=\"true\" />\n </a>\n <a\n href={`https://www.linkedin.com/sharing/share-offsite/?url=${encodedUrl}`}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n aria-label=\"Share on LinkedIn\"\n className=\"text-muted-foreground hover:text-foreground border-border inline-flex size-9 items-center justify-center rounded-full border grayscale transition-colors hover:border-[var(--blog-accent-border)] hover:bg-[var(--blog-accent-bg)]\"\n >\n <FaLinkedinIn className=\"size-4\" aria-hidden=\"true\" />\n </a>\n <a\n href={`mailto:?subject=${encodedTitle}&body=${encodedUrl}`}\n aria-label=\"Share by email\"\n className=\"text-muted-foreground hover:text-foreground border-border inline-flex size-9 items-center justify-center rounded-full border grayscale transition-colors hover:border-[var(--blog-accent-border)] hover:bg-[var(--blog-accent-bg)]\"\n >\n <Mail className=\"size-4\" aria-hidden=\"true\" />\n </a>\n </div>\n );\n}\n\nfunction RelatedArticles({\n articles,\n basePath,\n}: {\n articles: PublishedArticle[];\n basePath: string;\n}) {\n return (\n <section className=\"space-y-4\" aria-labelledby=\"related-articles-title\">\n <h2 id=\"related-articles-title\" className=\"text-xl font-semibold\">\n You might also like\n </h2>\n <div className=\"grid gap-4 md:grid-cols-3\">\n {articles.map((article) => (\n <Link\n key={article.id}\n href={buildBlogPath(basePath, article.slug)}\n className=\"group border-border overflow-hidden rounded-2xl border transition-colors hover:border-[var(--blog-accent-border)] hover:bg-[var(--blog-accent-bg)] hover:no-underline\"\n >\n {article.featuredImage && (\n <ArticleCardImage\n src={article.featuredImage}\n alt={\n article.featuredImageAlt ??\n `Featured image for ${article.title}`\n }\n />\n )}\n <div className=\"p-4\">\n <h3 className=\"text-foreground line-clamp-3 font-semibold transition-colors group-hover:text-[var(--blog-text-accent)]\">\n {article.title}\n </h3>\n {article.excerpt && (\n <p className=\"text-muted-foreground mt-2 line-clamp-3 text-sm leading-relaxed\">\n {article.excerpt}\n </p>\n )}\n </div>\n </Link>\n ))}\n </div>\n </section>\n );\n}\n\nfunction ArticleCardImage({ src, alt }: { src: string; alt: string }) {\n return (\n <div className=\"border-border aspect-[16/9] overflow-hidden border-b bg-[var(--blog-accent-bg)]\">\n <Image\n src={src}\n alt={alt}\n width={480}\n height={270}\n className=\"h-full w-full object-cover transition-transform duration-500 group-hover:scale-105\"\n />\n </div>\n );\n}\n\n/**\n * Generate metadata for the article page for SEO optimization.\n * This function should be used in the Next.js metadata API.\n */\nexport function generateArticleMetadata(\n article: PublishedArticle,\n basePath = \"/blog\",\n) {\n const title = article.meta.title ?? article.title;\n const description = article.meta.description ?? article.excerpt;\n const canonicalUrl =\n article.meta.canonicalUrl ??\n `${article.site.domain}${buildBlogPath(basePath, article.slug)}`;\n const ogImage = article.meta.ogImage ?? article.featuredImage;\n\n return {\n title,\n description,\n keywords: article.meta.keywords.join(\", \"),\n authors: article.author ? [{ name: article.author.name }] : undefined,\n openGraph: {\n title,\n description,\n type: \"article\",\n url: canonicalUrl,\n images: ogImage\n ? [{ url: ogImage, alt: article.featuredImageAlt ?? title }]\n : undefined,\n publishedTime: article.publishedAt,\n modifiedTime: article.updatedAt,\n authors: article.author ? [article.author.name] : undefined,\n siteName: article.site.name,\n },\n twitter: {\n card: \"summary_large_image\",\n title,\n description,\n images: ogImage ? [ogImage] : undefined,\n },\n alternates: {\n canonical: canonicalUrl,\n },\n };\n}\n","import React from \"react\";\nimport Image from \"next/image\";\nimport Link from \"next/link\";\nimport { ArrowLeft, Globe, Mail } from \"lucide-react\";\nimport { formatDistanceToNow } from \"date-fns\";\n\nimport Pagination from \"../../../../components/Pagination\";\nimport { Badge } from \"../../../../components/ui/badge\";\nimport { Separator } from \"../../../../components/ui/separator\";\nimport {\n createStructuredDataScript,\n generateAuthorStructuredData,\n} from \"../../../../lib/structured-data\";\nimport { cn } from \"../../../../lib/utils\";\nimport {\n buildBlogPath,\n buildAuthorPath,\n normalizeBlogBasePath,\n} from \"../../../../lib/urls\";\nimport { type BlogTheme, getBlogThemeStyle } from \"../../../../lib/article-ui\";\nimport type {\n PublishedArticle,\n PublishedAuthor,\n PublishedSite,\n} from \"../../../../types/contracts\";\n\ninterface AuthorPageProps {\n author: PublishedAuthor;\n articles: PublishedArticle[];\n site: PublishedSite;\n className?: string;\n basePath?: string;\n theme?: BlogTheme;\n pagination?: {\n currentPage: number;\n totalPages: number;\n baseUrl?: string;\n totalItems?: number;\n };\n navigation?: {\n backToHome?: {\n url: string;\n label?: string;\n };\n };\n}\n\nexport default function AuthorPage({\n author,\n articles,\n site,\n className,\n basePath = \"/blog\",\n theme,\n pagination,\n navigation,\n}: AuthorPageProps) {\n const normalizedBasePath = normalizeBlogBasePath(basePath) || \"/\";\n const backUrl = navigation?.backToHome?.url ?? normalizedBasePath;\n const authorUrl = buildAuthorPath(normalizedBasePath, author.slug);\n const totalArticleCount = pagination?.totalItems ?? articles.length;\n const structuredDataProps = createStructuredDataScript(\n generateAuthorStructuredData(author, {\n pathPrefix: normalizedBasePath,\n }),\n );\n\n return (\n <main\n style={getBlogThemeStyle(theme)}\n className={cn(\n \"author-page mx-auto max-w-5xl px-4 py-8 sm:px-6 sm:py-12 lg:px-8 lg:py-16\",\n className,\n )}\n >\n <header className=\"mb-10 space-y-8 sm:mb-14\">\n <Link\n href={backUrl}\n className=\"text-muted-foreground group focus-visible:ring-ring inline-flex items-center gap-2 rounded-md px-2 py-1 text-sm font-medium transition-colors hover:text-[var(--blog-accent)] focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-none\"\n >\n <ArrowLeft\n className=\"size-4 transition-transform group-hover:-translate-x-1\"\n aria-hidden=\"true\"\n />\n {navigation?.backToHome?.label ?? \"Back to all articles\"}\n </Link>\n\n <div className=\"grid gap-6 sm:grid-cols-[auto_minmax(0,1fr)] sm:items-center\">\n <AuthorAvatar author={author} />\n <div className=\"min-w-0 space-y-4\">\n <div className=\"space-y-2\">\n <div className=\"flex flex-wrap items-center gap-2\">\n {author.isGuest && (\n <Badge variant=\"outline\" className=\"text-xs\">\n Guest Author\n </Badge>\n )}\n </div>\n <h1 className=\"text-foreground text-4xl leading-tight font-semibold text-balance sm:text-5xl\">\n {author.name}\n </h1>\n </div>\n\n {author.bio && (\n <p className=\"text-muted-foreground max-w-3xl text-lg leading-relaxed text-pretty\">\n {author.bio}\n </p>\n )}\n\n <AuthorSocialLinks author={author} />\n </div>\n </div>\n </header>\n\n <Separator className=\"mb-8\" />\n\n <section aria-labelledby=\"author-articles-title\" className=\"space-y-6\">\n <div className=\"flex flex-wrap items-end justify-between gap-3\">\n <div>\n <h2\n id=\"author-articles-title\"\n className=\"text-foreground text-2xl font-semibold\"\n >\n Articles by {author.name}\n </h2>\n <p className=\"text-muted-foreground mt-1 text-sm\">\n {totalArticleCount}{\" \"}\n {totalArticleCount === 1 ? \"article\" : \"articles\"} on {site.name}\n </p>\n </div>\n </div>\n\n {articles.length === 0 ? (\n <p className=\"text-muted-foreground border-border rounded-2xl border p-6\">\n This author does not have any published articles yet.\n </p>\n ) : (\n <div className=\"divide-border divide-y\">\n {articles.map((article) => (\n <AuthorArticlePreview\n key={article.id}\n article={article}\n basePath={normalizedBasePath}\n />\n ))}\n </div>\n )}\n\n {pagination && pagination.totalPages > 1 && (\n <div className=\"pt-4\">\n <Pagination\n currentPage={pagination.currentPage}\n totalPages={pagination.totalPages}\n baseUrl={pagination.baseUrl ?? authorUrl}\n className=\"justify-center\"\n />\n </div>\n )}\n </section>\n\n <script\n type={structuredDataProps.type}\n dangerouslySetInnerHTML={structuredDataProps.dangerouslySetInnerHTML}\n />\n </main>\n );\n}\n\nfunction AuthorSocialLinks({ author }: { author: PublishedAuthor }) {\n const links = getAuthorSocialLinks(author);\n\n if (links.length === 0) {\n return null;\n }\n\n return (\n <div\n className=\"flex flex-wrap items-center gap-2\"\n aria-label=\"Author links\"\n >\n {links.map((link) => (\n <a\n key={link.label}\n href={link.href}\n target={link.external ? \"_blank\" : undefined}\n rel={link.external ? \"noopener noreferrer\" : undefined}\n aria-label={link.ariaLabel}\n className=\"text-muted-foreground hover:text-foreground border-border inline-flex size-9 items-center justify-center rounded-full border grayscale transition-colors hover:border-[var(--blog-accent-border)] hover:bg-[var(--blog-accent-bg)]\"\n >\n {link.icon}\n </a>\n ))}\n </div>\n );\n}\n\nfunction getAuthorSocialLinks(author: PublishedAuthor) {\n const links = author.socialLinks;\n\n if (!links) {\n return [];\n }\n\n return [\n links.website\n ? {\n href: links.website,\n label: \"website\",\n ariaLabel: `${author.name}'s website`,\n external: true,\n icon: <Globe className=\"size-4\" aria-hidden=\"true\" />,\n }\n : null,\n (links.x ?? links.twitter)\n ? {\n href: links.x ?? links.twitter ?? \"\",\n label: \"x\",\n ariaLabel: `${author.name} on X`,\n external: true,\n icon: (\n <span className=\"text-sm font-semibold\" aria-hidden=\"true\">\n X\n </span>\n ),\n }\n : null,\n links.linkedin\n ? {\n href: links.linkedin,\n label: \"linkedin\",\n ariaLabel: `${author.name} on LinkedIn`,\n external: true,\n icon: (\n <span className=\"text-sm font-bold\" aria-hidden=\"true\">\n in\n </span>\n ),\n }\n : null,\n links.github\n ? {\n href: links.github,\n label: \"github\",\n ariaLabel: `${author.name} on GitHub`,\n external: true,\n icon: (\n <span className=\"text-xs font-bold\" aria-hidden=\"true\">\n GH\n </span>\n ),\n }\n : null,\n links.email\n ? {\n href: `mailto:${links.email}`,\n label: \"email\",\n ariaLabel: `Email ${author.name}`,\n external: false,\n icon: <Mail className=\"size-4\" aria-hidden=\"true\" />,\n }\n : null,\n ].filter((link): link is NonNullable<typeof link> => link !== null);\n}\n\nfunction AuthorArticlePreview({\n article,\n basePath,\n}: {\n article: PublishedArticle;\n basePath: string;\n}) {\n const publishedRelativeLabel = formatDistanceToNow(\n new Date(article.publishedAt),\n { addSuffix: true },\n );\n\n return (\n <article className=\"py-6 first:pt-0 last:pb-0\">\n <Link\n href={buildBlogPath(basePath, article.slug)}\n className=\"group grid gap-4 hover:no-underline sm:grid-cols-[minmax(0,1fr)_12rem] sm:items-start\"\n >\n <div className=\"min-w-0 space-y-3\">\n <h3 className=\"text-xl leading-tight font-semibold text-balance transition-colors group-hover:text-[var(--blog-text-accent)]\">\n {article.title}\n </h3>\n {article.excerpt && (\n <p className=\"text-muted-foreground line-clamp-3 leading-relaxed\">\n {article.excerpt}\n </p>\n )}\n <div className=\"text-muted-foreground flex flex-wrap items-center gap-x-3 gap-y-1 text-sm\">\n <time dateTime={article.publishedAt}>{publishedRelativeLabel}</time>\n <span aria-hidden=\"true\">•</span>\n <span>{Math.ceil(article.readingSeconds / 60)} min read</span>\n </div>\n </div>\n\n {article.featuredImage && (\n <div className=\"border-border relative aspect-[16/10] overflow-hidden rounded-xl border bg-[var(--blog-accent-bg)]\">\n <Image\n src={article.featuredImage}\n alt={\n article.featuredImageAlt ??\n `Featured image for ${article.title}`\n }\n width={320}\n height={200}\n className=\"h-full w-full object-cover transition-transform duration-500 group-hover:scale-105\"\n />\n </div>\n )}\n </Link>\n </article>\n );\n}\n\nfunction AuthorAvatar({ author }: { author: PublishedAuthor }) {\n if (author.avatarUrl) {\n return (\n <Image\n src={author.avatarUrl}\n alt={author.name}\n width={128}\n height={128}\n className=\"size-28 rounded-full border border-[var(--blog-accent-border)] object-cover sm:size-32\"\n priority\n />\n );\n }\n\n return (\n <span className=\"bg-muted text-muted-foreground inline-flex size-28 items-center justify-center rounded-full text-3xl font-semibold sm:size-32\">\n {getAuthorInitials(author.name)}\n </span>\n );\n}\n\nfunction getAuthorInitials(name: string): string {\n const initials = name\n .trim()\n .split(/\\s+/)\n .filter(Boolean)\n .slice(0, 2)\n .map((part) => part[0]?.toUpperCase())\n .join(\"\");\n\n return initials || \"?\";\n}\n\nexport function generateAuthorPageMetadata(\n author: PublishedAuthor,\n site: PublishedSite,\n basePath = \"/blog\",\n) {\n const canonicalUrl = `https://${site.domain\n .replace(/^https?:\\/\\//, \"\")\n .replace(/\\/+$/, \"\")}${buildAuthorPath(basePath, author.slug)}`;\n const title = `${author.name} - ${site.name}`;\n const description =\n author.bio ?? `Read articles by ${author.name} on ${site.name}.`;\n\n return {\n title,\n description,\n authors: [{ name: author.name }],\n openGraph: {\n title,\n description,\n type: \"profile\",\n url: canonicalUrl,\n images: author.avatarUrl\n ? [{ url: author.avatarUrl, alt: author.name }]\n : undefined,\n siteName: site.name,\n },\n twitter: {\n card: author.avatarUrl ? \"summary_large_image\" : \"summary\",\n title,\n description,\n images: author.avatarUrl ? [author.avatarUrl] : undefined,\n },\n alternates: {\n canonical: canonicalUrl,\n },\n };\n}\n","/**\n * Database interface for blog platform storage\n *\n * This provides a simple interface for storing published articles\n * without coupling to any specific database implementation.\n * Customers can implement this interface with their preferred database.\n */\n\nimport type { PublishedArticle, PublishResult } from \"@/types/contracts\";\n\nexport interface BlogPlatformStorage {\n /**\n * Store a published article\n */\n saveArticle(\n article: PublishedArticle,\n idempotencyKey: string,\n ): Promise<PublishResult>;\n\n /**\n * Get an article by slug\n */\n getArticle(slug: string): Promise<PublishedArticle | null>;\n\n /**\n * List all published articles\n */\n listArticles(options?: {\n limit?: number;\n offset?: number;\n sortBy?: \"publishedAt\" | \"updatedAt\";\n order?: \"asc\" | \"desc\";\n }): Promise<{\n articles: PublishedArticle[];\n total: number;\n }>;\n\n /**\n * Remove an article by slug\n */\n removeArticle(slug: string, idempotencyKey: string): Promise<PublishResult>;\n\n /**\n * Check if an operation was already performed (idempotency)\n */\n checkIdempotency(idempotencyKey: string): Promise<PublishResult | null>;\n\n /**\n * Store the result of an operation for idempotency\n */\n storeOperationResult(\n idempotencyKey: string,\n result: PublishResult,\n ): Promise<void>;\n}\n\n/**\n * Default in-memory storage implementation for development/testing\n * IMPORTANT: This is not suitable for production use!\n */\nexport class InMemoryStorage implements BlogPlatformStorage {\n private articles = new Map<string, PublishedArticle>();\n private operations = new Map<string, PublishResult>();\n\n async saveArticle(\n article: PublishedArticle,\n idempotencyKey: string,\n ): Promise<PublishResult> {\n // Check for existing idempotency key\n const existingResult = await this.checkIdempotency(idempotencyKey);\n\n // CRITICAL FIX: Allow republish after unpublish\n // If we found a cached operation result AND it was successful,\n // check if the article still exists. If it was removed (unpublished),\n // proceed with the save to allow republishing.\n if (existingResult) {\n if (existingResult.success) {\n // Check if article still exists by finding it in the articles map\n const articleStillExists = Array.from(this.articles.values()).some(\n (a) => a.id === article.id,\n );\n\n // If article was removed, allow republish by not returning cached result\n if (!articleStillExists) {\n // Article was unpublished - proceed with save\n } else {\n // Article still exists - this is a true duplicate\n return existingResult;\n }\n } else {\n // Failed operations are always returned as-is\n return existingResult;\n }\n }\n\n // Validate slug uniqueness\n if (this.articles.has(article.slug)) {\n const result: PublishResult = {\n success: false,\n error: {\n code: \"PUB003\",\n message: \"This URL is already in use. Please choose another.\",\n },\n idempotencyKey,\n };\n await this.storeOperationResult(idempotencyKey, result);\n return result;\n }\n\n // Store the article\n this.articles.set(article.slug, article);\n\n const result: PublishResult = {\n success: true,\n url: `/${article.slug}`,\n platformPostId: article.id,\n publishedAt: article.publishedAt,\n idempotencyKey,\n };\n\n await this.storeOperationResult(idempotencyKey, result);\n return result;\n }\n\n async getArticle(slug: string): Promise<PublishedArticle | null> {\n return this.articles.get(slug) ?? null;\n }\n\n async listArticles(\n options: {\n limit?: number;\n offset?: number;\n sortBy?: \"publishedAt\" | \"updatedAt\";\n order?: \"asc\" | \"desc\";\n } = {},\n ): Promise<{ articles: PublishedArticle[]; total: number }> {\n const {\n limit = 10,\n offset = 0,\n sortBy = \"publishedAt\",\n order = \"desc\",\n } = options;\n\n const allArticles = Array.from(this.articles.values());\n\n // Sort articles\n allArticles.sort((a, b) => {\n const aValue = new Date(a[sortBy]).getTime();\n const bValue = new Date(b[sortBy]).getTime();\n return order === \"desc\" ? bValue - aValue : aValue - bValue;\n });\n\n // Apply pagination\n const articles = allArticles.slice(offset, offset + limit);\n\n return {\n articles,\n total: allArticles.length,\n };\n }\n\n async removeArticle(\n slug: string,\n idempotencyKey: string,\n ): Promise<PublishResult> {\n // Check for existing idempotency key\n const existingResult = await this.checkIdempotency(idempotencyKey);\n\n // CRITICAL FIX: Allow re-unpublish after republish\n // If we found a cached operation result AND it was successful,\n // check if the article NOW exists. If it was republished,\n // proceed with the removal to allow re-unpublishing.\n if (existingResult) {\n if (existingResult.success) {\n // Check if article exists NOW (might have been republished)\n const articleExists = this.articles.has(slug);\n\n // If article EXISTS, it was republished - allow re-unpublish\n if (articleExists) {\n // Article was republished - proceed with removal\n } else {\n // Article still removed - this is a true duplicate\n return existingResult;\n }\n } else {\n // Failed operations are always returned as-is\n return existingResult;\n }\n }\n\n // Check if article exists\n if (!this.articles.has(slug)) {\n const result: PublishResult = {\n success: false,\n error: {\n code: \"PUB007\",\n message: \"Article not found\",\n },\n idempotencyKey,\n };\n await this.storeOperationResult(idempotencyKey, result);\n return result;\n }\n\n // Remove the article\n this.articles.delete(slug);\n\n const result: PublishResult = {\n success: true,\n idempotencyKey,\n };\n\n await this.storeOperationResult(idempotencyKey, result);\n return result;\n }\n\n async checkIdempotency(\n idempotencyKey: string,\n ): Promise<PublishResult | null> {\n return this.operations.get(idempotencyKey) ?? null;\n }\n\n async storeOperationResult(\n idempotencyKey: string,\n result: PublishResult,\n ): Promise<void> {\n this.operations.set(idempotencyKey, result);\n }\n}\n\ntype GlobalWithStorage = typeof globalThis & {\n __BLOG_PLATFORM_STORAGE__?: BlogPlatformStorage;\n __BLOG_PLATFORM_STORAGE_WARNED__?: boolean;\n};\n\nfunction warnAboutEphemeralStorage(): void {\n const globalRef = globalThis as GlobalWithStorage;\n if (globalRef.__BLOG_PLATFORM_STORAGE_WARNED__) {\n return;\n }\n\n globalRef.__BLOG_PLATFORM_STORAGE_WARNED__ = true;\n\n const message =\n \"Blog platform: No storage provider configured. Falling back to in-memory storage (data is not persisted).\";\n if (process.env.NODE_ENV === \"production\") {\n console.error(\n `${message} Call initBlogPlatform({ storage: /* your persistent adapter */ }) to avoid data loss.`,\n );\n } else {\n console.warn(message);\n }\n}\n\nfunction getGlobalStorage(): BlogPlatformStorage {\n const globalRef = globalThis as GlobalWithStorage;\n if (!globalRef.__BLOG_PLATFORM_STORAGE__) {\n warnAboutEphemeralStorage();\n globalRef.__BLOG_PLATFORM_STORAGE__ = new InMemoryStorage();\n }\n const storage = globalRef.__BLOG_PLATFORM_STORAGE__;\n if (!storage) {\n // This should be unreachable because we set it above,\n // but the guard satisfies strict type checking without assertions.\n throw new Error(\"Blog platform storage not initialized\");\n }\n return storage;\n}\n\nexport function getStorage(): BlogPlatformStorage {\n return getGlobalStorage();\n}\n\nexport function setStorage(storage: BlogPlatformStorage): void {\n const globalRef = globalThis as GlobalWithStorage;\n globalRef.__BLOG_PLATFORM_STORAGE__ = storage;\n}\n","import type { BlogPlatformStorage } from \"./database\";\nimport { getStorage } from \"./database\";\nimport type { PublishedArticle, PublishedAuthor } from \"../types/contracts\";\n\nexport interface AuthorArchive {\n author: PublishedAuthor;\n articles: PublishedArticle[];\n}\n\nexport interface AuthorArchiveOptions {\n limit?: number;\n offset?: number;\n}\n\nexport function getAuthorsFromArticles(\n articles: readonly PublishedArticle[],\n): PublishedAuthor[] {\n const authorsBySlug = new Map<string, PublishedAuthor>();\n\n for (const article of articles) {\n if (article.author?.slug) {\n authorsBySlug.set(\n article.author.slug,\n mergeAuthorProfile(\n authorsBySlug.get(article.author.slug),\n article.author,\n ),\n );\n }\n }\n\n return Array.from(authorsBySlug.values()).sort((a, b) =>\n a.name.localeCompare(b.name),\n );\n}\n\nexport function getAuthorArchive(\n slug: string,\n articles: readonly PublishedArticle[],\n): AuthorArchive | null {\n const authorArticles = articles\n .filter((article) => article.author?.slug === slug)\n .sort(\n (a, b) =>\n new Date(b.publishedAt).getTime() - new Date(a.publishedAt).getTime(),\n );\n\n const author = authorArticles.reduce<PublishedAuthor | null>(\n (preferredAuthor, article) =>\n article.author\n ? mergeAuthorProfile(preferredAuthor, article.author)\n : preferredAuthor,\n null,\n );\n\n if (!author) {\n return null;\n }\n\n return {\n author,\n articles: authorArticles,\n };\n}\n\nexport async function loadAuthorArchive(\n slug: string,\n options: AuthorArchiveOptions = {},\n storage: BlogPlatformStorage = getStorage(),\n): Promise<AuthorArchive | null> {\n const { articles } = await storage.listArticles({\n limit: options.limit ?? 1000,\n offset: options.offset ?? 0,\n sortBy: \"publishedAt\",\n order: \"desc\",\n });\n\n return getAuthorArchive(slug, articles);\n}\n\nfunction mergeAuthorProfile(\n current: PublishedAuthor | null | undefined,\n next: PublishedAuthor,\n): PublishedAuthor {\n if (!current) {\n return next;\n }\n\n return {\n ...current,\n bio: current.bio ?? next.bio,\n avatarUrl: current.avatarUrl ?? next.avatarUrl,\n pronouns: current.pronouns ?? next.pronouns,\n socialLinks: current.socialLinks ?? next.socialLinks,\n toneAdjectives:\n current.toneAdjectives.length > 0\n ? current.toneAdjectives\n : next.toneAdjectives,\n };\n}\n","import type { PublishedArticle, PublishedTopic } from \"../types/contracts\";\n\nexport interface TopicArchive {\n topic: PublishedTopic;\n articles: PublishedArticle[];\n}\n\nexport function getArticlePrimaryTopic(\n article: PublishedArticle,\n): PublishedTopic | null {\n const topics = article.topics ?? [];\n return topics.find((topic) => topic.isPrimary) ?? topics[0] ?? null;\n}\n\nexport function getAllTopics(articles: PublishedArticle[]): PublishedTopic[] {\n const topicsBySlug = new Map<string, PublishedTopic>();\n\n for (const article of articles) {\n for (const topic of article.topics ?? []) {\n if (!topicsBySlug.has(topic.slug)) {\n topicsBySlug.set(topic.slug, topic);\n }\n }\n }\n\n return Array.from(topicsBySlug.values()).sort((a, b) =>\n a.name.localeCompare(b.name),\n );\n}\n\nexport function getTopicArchive(\n articles: PublishedArticle[],\n topicSlug: string,\n): TopicArchive | null {\n const matchingArticles = articles.filter((article) =>\n (article.topics ?? []).some((topic) => topic.slug === topicSlug),\n );\n\n if (matchingArticles.length === 0) {\n return null;\n }\n\n const topic =\n matchingArticles\n .flatMap((article) => article.topics ?? [])\n .find((candidate) => candidate.slug === topicSlug) ?? null;\n\n if (!topic) {\n return null;\n }\n\n return {\n topic,\n articles: matchingArticles,\n };\n}\n","import React from \"react\";\nimport Link from \"next/link\";\nimport Image from \"next/image\";\nimport { formatDistanceToNow } from \"date-fns\";\n\nimport type { PublishedArticle, PublishedTopic } from \"../types/contracts\";\nimport type { BlogTheme } from \"../lib/article-ui\";\nimport { getBlogThemeStyle } from \"../lib/article-ui\";\nimport { buildBlogPath, normalizeBlogBasePath } from \"../lib/urls\";\nimport { cn } from \"../lib/utils\";\nimport { getAllTopics, getTopicArchive } from \"../lib/topics\";\n\ninterface BlogTopicsIndexPageProps {\n articles: PublishedArticle[];\n basePath?: string;\n title?: string;\n description?: string;\n className?: string;\n theme?: BlogTheme;\n}\n\ninterface BlogTopicArchivePageProps {\n articles: PublishedArticle[];\n topicSlug: string;\n basePath?: string;\n className?: string;\n theme?: BlogTheme;\n}\n\nexport function BlogTopicsIndexPage({\n articles,\n basePath = \"/blog\",\n title = \"Topics\",\n description = \"Browse articles by topic.\",\n className,\n theme,\n}: BlogTopicsIndexPageProps) {\n const normalizedBasePath = normalizeBlogBasePath(basePath) || \"/\";\n const topics = getAllTopics(articles);\n\n return (\n <main\n style={getBlogThemeStyle(theme)}\n className={cn(\n \"blog-topics-page container mx-auto max-w-5xl px-4 py-8 sm:px-6 sm:py-12 lg:px-8 lg:py-16\",\n className,\n )}\n >\n <header className=\"mb-10 space-y-3 text-center\">\n <Link\n href={normalizedBasePath}\n className=\"text-muted-foreground hover:text-[var(--blog-accent)] text-sm font-medium transition-colors\"\n >\n Back to all articles\n </Link>\n <h1 className=\"text-4xl font-semibold tracking-tight text-balance sm:text-5xl\">\n {title}\n </h1>\n <p className=\"text-muted-foreground mx-auto max-w-2xl text-lg text-pretty\">\n {description}\n </p>\n </header>\n\n {topics.length === 0 ? (\n <p className=\"text-muted-foreground rounded-2xl border p-8 text-center\">\n No topics have published articles yet.\n </p>\n ) : (\n <div className=\"grid gap-4 sm:grid-cols-2 lg:grid-cols-3\">\n {topics.map((topic) => {\n const count = articles.filter((article) =>\n (article.topics ?? []).some(\n (articleTopic) => articleTopic.slug === topic.slug,\n ),\n ).length;\n\n return (\n <Link\n key={topic.slug}\n href={buildBlogPath(normalizedBasePath, `topics/${topic.slug}`)}\n className=\"group rounded-2xl border border-[var(--blog-accent-border)] bg-[var(--blog-card-bg)] p-5 transition hover:border-[var(--blog-accent)] hover:no-underline\"\n >\n <h2 className=\"group-hover:text-[var(--blog-accent)] text-xl font-semibold transition-colors\">\n {topic.name}\n </h2>\n {topic.description && (\n <p className=\"text-muted-foreground mt-2 line-clamp-3 text-sm leading-relaxed\">\n {topic.description}\n </p>\n )}\n <p className=\"text-muted-foreground mt-4 text-sm\">\n {count} {count === 1 ? \"article\" : \"articles\"}\n </p>\n </Link>\n );\n })}\n </div>\n )}\n </main>\n );\n}\n\nexport function BlogTopicArchivePage({\n articles,\n topicSlug,\n basePath = \"/blog\",\n className,\n theme,\n}: BlogTopicArchivePageProps) {\n const normalizedBasePath = normalizeBlogBasePath(basePath) || \"/\";\n const archive = getTopicArchive(articles, topicSlug);\n\n return (\n <main\n style={getBlogThemeStyle(theme)}\n className={cn(\n \"blog-topic-archive-page container mx-auto max-w-5xl px-4 py-8 sm:px-6 sm:py-12 lg:px-8 lg:py-16\",\n className,\n )}\n >\n <header className=\"mb-10 space-y-3 text-center\">\n <Link\n href={buildBlogPath(normalizedBasePath, \"topics\")}\n className=\"text-muted-foreground hover:text-[var(--blog-accent)] text-sm font-medium transition-colors\"\n >\n Back to all topics\n </Link>\n <h1 className=\"text-4xl font-semibold tracking-tight text-balance sm:text-5xl\">\n {archive?.topic.name ?? \"Topic not found\"}\n </h1>\n {archive?.topic.description && (\n <p className=\"text-muted-foreground mx-auto max-w-2xl text-lg text-pretty\">\n {archive.topic.description}\n </p>\n )}\n </header>\n\n {!archive ? (\n <p className=\"text-muted-foreground rounded-2xl border p-8 text-center\">\n No published articles were found for this topic.\n </p>\n ) : (\n <div className=\"grid gap-5 md:grid-cols-2\">\n {archive.articles.map((article) => (\n <TopicArticleCard\n key={article.id}\n article={article}\n topic={archive.topic}\n basePath={normalizedBasePath}\n />\n ))}\n </div>\n )}\n </main>\n );\n}\n\nfunction TopicArticleCard({\n article,\n topic,\n basePath,\n}: {\n article: PublishedArticle;\n topic: PublishedTopic;\n basePath: string;\n}) {\n const articleUrl = buildBlogPath(basePath, article.slug);\n const publishedAgo = formatDistanceToNow(new Date(article.publishedAt), {\n addSuffix: true,\n });\n\n return (\n <Link\n href={articleUrl}\n className=\"group overflow-hidden rounded-2xl border border-[var(--blog-accent-border)] bg-[var(--blog-card-bg)] transition hover:border-[var(--blog-accent)] hover:no-underline\"\n >\n {article.featuredImage && (\n <div className=\"relative aspect-[16/9] overflow-hidden\">\n <Image\n src={article.featuredImage}\n alt={article.featuredImageAlt ?? article.title}\n width={640}\n height={360}\n className=\"h-full w-full object-cover transition-transform duration-300 group-hover:scale-105\"\n />\n </div>\n )}\n <div className=\"space-y-3 p-5\">\n <span className=\"inline-flex rounded-full border border-[var(--blog-accent-border)] px-2.5 py-1 text-xs font-medium text-[var(--blog-text-accent)]\">\n {topic.name}\n </span>\n <h2 className=\"group-hover:text-[var(--blog-accent)] text-xl font-semibold text-balance transition-colors\">\n {article.title}\n </h2>\n {article.excerpt && (\n <p className=\"text-muted-foreground line-clamp-3 text-sm leading-relaxed\">\n {article.excerpt}\n </p>\n )}\n <p className=\"text-muted-foreground text-sm\">{publishedAgo}</p>\n </div>\n </Link>\n );\n}\n","import React from \"react\";\nimport Image from \"next/image\";\nimport Link from \"next/link\";\n\nimport type { PublishedArticle, PublishedAuthor } from \"../types/contracts\";\nimport type { BlogTheme } from \"../lib/article-ui\";\nimport { getBlogThemeStyle } from \"../lib/article-ui\";\nimport { getAuthorsFromArticles } from \"../lib/authors\";\nimport { buildAuthorPath, normalizeBlogBasePath } from \"../lib/urls\";\nimport { cn } from \"../lib/utils\";\n\ninterface BlogAuthorsIndexPageProps {\n articles: PublishedArticle[];\n basePath?: string;\n title?: string;\n description?: string;\n className?: string;\n theme?: BlogTheme;\n}\n\nexport function BlogAuthorsIndexPage({\n articles,\n basePath = \"/blog\",\n title = \"Authors\",\n description = \"Browse articles by author.\",\n className,\n theme,\n}: BlogAuthorsIndexPageProps) {\n const normalizedBasePath = normalizeBlogBasePath(basePath) || \"/\";\n const authors = getAuthorsFromArticles(articles);\n\n return (\n <main\n style={getBlogThemeStyle(theme)}\n className={cn(\n \"blog-authors-page container mx-auto max-w-5xl px-4 py-8 sm:px-6 sm:py-12 lg:px-8 lg:py-16\",\n className,\n )}\n >\n <header className=\"mb-10 space-y-3 text-center\">\n <Link\n href={normalizedBasePath}\n className=\"text-muted-foreground text-sm font-medium transition-colors hover:text-[var(--blog-accent)]\"\n >\n Back to all articles\n </Link>\n <h1 className=\"text-4xl font-semibold tracking-tight text-balance sm:text-5xl\">\n {title}\n </h1>\n <p className=\"text-muted-foreground mx-auto max-w-2xl text-lg text-pretty\">\n {description}\n </p>\n </header>\n\n {authors.length === 0 ? (\n <p className=\"text-muted-foreground rounded-2xl border p-8 text-center\">\n No authors have published articles yet.\n </p>\n ) : (\n <div className=\"grid gap-4 sm:grid-cols-2 lg:grid-cols-3\">\n {authors.map((author) => {\n const count = articles.filter(\n (article) => article.author?.slug === author.slug,\n ).length;\n\n return (\n <Link\n key={author.slug}\n href={buildAuthorPath(normalizedBasePath, author.slug)}\n className=\"group rounded-2xl border border-[var(--blog-accent-border)] bg-[var(--blog-card-bg)] p-5 transition hover:border-[var(--blog-accent)] hover:no-underline\"\n >\n <div className=\"flex items-start gap-4\">\n <AuthorAvatar author={author} />\n <div className=\"min-w-0 space-y-2\">\n <h2 className=\"text-xl font-semibold transition-colors group-hover:text-[var(--blog-accent)]\">\n {author.name}\n </h2>\n {author.bio && (\n <p className=\"text-muted-foreground line-clamp-3 text-sm leading-relaxed\">\n {author.bio}\n </p>\n )}\n <p className=\"text-muted-foreground text-sm\">\n {count} {count === 1 ? \"article\" : \"articles\"}\n </p>\n </div>\n </div>\n </Link>\n );\n })}\n </div>\n )}\n </main>\n );\n}\n\nfunction AuthorAvatar({ author }: { author: PublishedAuthor }) {\n const initials = getAuthorInitials(author.name);\n\n if (author.avatarUrl) {\n return (\n <Image\n src={author.avatarUrl}\n alt={author.name}\n width={56}\n height={56}\n className=\"size-14 shrink-0 rounded-full border border-[var(--blog-accent-border)] object-cover\"\n />\n );\n }\n\n return (\n <span className=\"bg-muted text-muted-foreground inline-flex size-14 shrink-0 items-center justify-center rounded-full text-base font-semibold\">\n {initials}\n </span>\n );\n}\n\nfunction getAuthorInitials(name: string): string {\n const initials = name\n .trim()\n .split(/\\s+/)\n .filter(Boolean)\n .slice(0, 2)\n .map((part) => part[0]?.toUpperCase())\n .join(\"\");\n\n return initials || \"?\";\n}\n","import { type NextRequest } from \"next/server\";\nimport type { PublishResult } from \"@/types/contracts\";\n\n/**\n * Authentication configuration interface\n * Customers can implement this to customize authentication behavior\n */\nexport interface AuthConfig {\n /**\n * Validate an authentication token\n * @param token - The token to validate\n * @returns Promise that resolves to validation result\n */\n validateToken(token: string): Promise<AuthResult>;\n \n /**\n * Extract token from request\n * @param request - The incoming request\n * @returns The extracted token or null if not found\n */\n extractToken?(request: NextRequest): string | null;\n \n /**\n * Custom error messages for authentication failures\n */\n errorMessages?: {\n missing?: string;\n invalid?: string;\n expired?: string;\n };\n}\n\n/**\n * Authentication result from token validation\n */\nexport interface AuthResult {\n /** Whether the token is valid */\n valid: boolean;\n \n /** Error code if invalid */\n errorCode?: \"missing\" | \"invalid\" | \"expired\";\n \n /** Additional user/context information */\n context?: Record<string, unknown>;\n}\n\n/**\n * Default token extraction from Authorization header\n * Supports both \"Bearer <token>\" and \"Token <token>\" formats\n */\nexport function extractTokenFromHeader(request: NextRequest): string | null {\n const authHeader = request.headers.get(\"Authorization\");\n if (!authHeader) {\n return null;\n }\n\n // Support both \"Bearer <token>\" and \"Token <token>\" formats\n const bearerRegex = /^Bearer\\s+(.+)$/i;\n const bearerMatch = bearerRegex.exec(authHeader);\n if (bearerMatch?.[1]) {\n return bearerMatch[1];\n }\n\n const tokenRegex = /^Token\\s+(.+)$/i;\n const tokenMatch = tokenRegex.exec(authHeader);\n if (tokenMatch?.[1]) {\n return tokenMatch[1];\n }\n\n return null;\n}\n\n/**\n * Simple API key based authentication implementation\n * Customers can extend this or provide their own AuthConfig\n */\nexport class ApiKeyAuth implements AuthConfig {\n private validApiKeys: Set<string>;\n \n constructor(apiKeys: string[]) {\n this.validApiKeys = new Set(apiKeys);\n }\n\n async validateToken(token: string): Promise<AuthResult> {\n if (!token?.trim()) {\n return {\n valid: false,\n errorCode: \"missing\",\n };\n }\n\n if (this.validApiKeys.has(token)) {\n return {\n valid: true,\n context: {\n tokenHash: this.hashToken(token),\n },\n };\n }\n\n return {\n valid: false,\n errorCode: \"invalid\",\n };\n }\n\n extractToken = (request: NextRequest): string | null => {\n return extractTokenFromHeader(request);\n };\n\n private hashToken(token: string): string {\n // Simple hash for logging/debugging (first 8 chars)\n return token.substring(0, 8) + \"...\";\n }\n}\n\n/**\n * Environment variable based authentication\n * Reads API keys from environment variables\n */\nexport class EnvAuth extends ApiKeyAuth {\n constructor(envVarName = \"BLOG_PLATFORM_API_KEYS\") {\n let apiKeysEnv = process.env[envVarName];\n\n // Backwards compatibility: fall back to BLOG_AUTH_TOKEN when using default env var\n if (!apiKeysEnv && envVarName === \"BLOG_PLATFORM_API_KEYS\") {\n apiKeysEnv = process.env.BLOG_AUTH_TOKEN;\n }\n\n const apiKeys = apiKeysEnv ? apiKeysEnv.split(\",\").map((key) => key.trim()).filter(Boolean) : [];\n\n if (apiKeys.length === 0) {\n const hint = envVarName === \"BLOG_PLATFORM_API_KEYS\"\n ? \" (set BLOG_PLATFORM_API_KEYS or BLOG_AUTH_TOKEN)\"\n : \"\";\n console.warn(\n `⚠️ No API keys found in environment variable ${envVarName}${hint}. Authentication will fail for all requests.`,\n );\n }\n\n super(apiKeys);\n }\n}\n\n/**\n * No-op authentication for development/testing\n * WARNING: Never use this in production!\n */\nexport class NoAuth implements AuthConfig {\n async validateToken(): Promise<AuthResult> {\n return {\n valid: true,\n context: {\n development: true,\n },\n };\n }\n\n extractToken(): string | null {\n return \"development-mode\";\n }\n}\n\n/**\n * Uninitialized authentication - rejects all requests\n * This is the secure default before initialization\n */\nexport class UninitializedAuth implements AuthConfig {\n private hasWarned = false;\n\n async validateToken(_token: string): Promise<AuthResult> {\n if (!this.hasWarned) {\n console.error(\n \"❌ SECURITY WARNING: Blog platform authentication not initialized! \" +\n \"All requests will be rejected. Call initBlogPlatform() to configure authentication.\"\n );\n this.hasWarned = true;\n }\n\n return {\n valid: false,\n errorCode: \"invalid\",\n };\n }\n\n // Don't override extractToken - use default header extraction\n // Don't override error messages - use defaults so users see\n // \"Invalid authentication credentials\" instead of confusing\n // \"platform not initialized\" messages\n}\n\ndeclare global {\n // Using `var` here intentionally to declare a global on Node's globalThis\n // across module boundaries and hot reloads\n var __BLOG_PLATFORM_AUTH_CONFIG__: AuthConfig | undefined;\n}\n\n/**\n * Global authentication configuration\n * Defaults to UninitializedAuth for security (fail closed)\n * Stored in globalThis to persist across Next.js dev mode hot reloads\n */\nfunction getDefaultAuthConfig(): AuthConfig {\n globalThis.__BLOG_PLATFORM_AUTH_CONFIG__ ??= new UninitializedAuth();\n return globalThis.__BLOG_PLATFORM_AUTH_CONFIG__;\n}\n\n/**\n * Set the authentication configuration\n * Customers should call this in their app initialization\n */\nexport function setAuthConfig(config: AuthConfig): void {\n globalThis.__BLOG_PLATFORM_AUTH_CONFIG__ = config;\n}\n\n/**\n * Get the current authentication configuration\n */\nexport function getAuthConfig(): AuthConfig {\n return globalThis.__BLOG_PLATFORM_AUTH_CONFIG__ ?? getDefaultAuthConfig();\n}\n\n/**\n * Initialize authentication with environment-based API keys\n * This is a convenience function for common setups\n */\nexport function initEnvAuth(envVarName?: string): void {\n setAuthConfig(new EnvAuth(envVarName));\n}\n\n/**\n * Authenticate an incoming request\n * @param request - The Next.js request object\n * @returns Authentication result with token validation\n */\nexport async function authenticateRequest(request: NextRequest): Promise<{\n authenticated: boolean;\n result: AuthResult;\n token: string | null;\n}> {\n const config = getAuthConfig();\n\n // Extract token using configured method or default\n const token = config.extractToken ? config.extractToken(request) : extractTokenFromHeader(request);\n\n if (!token) {\n return {\n authenticated: false,\n result: {\n valid: false,\n errorCode: \"missing\",\n },\n token: null,\n };\n }\n\n // Validate the token\n const result = await config.validateToken(token);\n\n return {\n authenticated: result.valid,\n result,\n token,\n };\n}\n\n/**\n * Create an authentication error response\n * @param authResult - The failed authentication result\n * @param idempotencyKey - Optional idempotency key from request\n * @returns NextResponse with appropriate error\n */\nexport function createAuthErrorResponse(\n authResult: AuthResult,\n idempotencyKey = \"\"\n): PublishResult {\n const config = getAuthConfig();\n const customMessages = config.errorMessages ?? {};\n \n let message: string;\n let code: string;\n \n switch (authResult.errorCode) {\n case \"missing\":\n message = customMessages.missing ?? \"Authentication token is required\";\n code = \"PUB005\";\n break;\n case \"expired\":\n message = customMessages.expired ?? \"Authentication token has expired\";\n code = \"PUB005\";\n break;\n case \"invalid\":\n default:\n message = customMessages.invalid ?? \"Invalid authentication credentials\";\n code = \"PUB005\";\n break;\n }\n\n return {\n success: false,\n error: {\n code,\n message,\n details: {\n authError: authResult.errorCode ?? \"invalid\",\n },\n },\n idempotencyKey,\n };\n}\n\n/**\n * Middleware function to protect API endpoints\n * Usage in route handlers:\n * \n * ```typescript\n * export async function POST(request: NextRequest) {\n * const authCheck = await requireAuth(request);\n * if (!authCheck.authenticated) {\n * return NextResponse.json(authCheck.error, { status: 401 });\n * }\n * \n * // Continue with authenticated request...\n * }\n * ```\n */\nexport async function requireAuth(request: NextRequest): Promise<{\n authenticated: boolean;\n error?: PublishResult;\n context?: Record<string, unknown>;\n}> {\n const auth = await authenticateRequest(request);\n \n if (!auth.authenticated) {\n return {\n authenticated: false,\n error: createAuthErrorResponse(auth.result),\n };\n }\n\n return {\n authenticated: true,\n context: auth.result.context,\n };\n}\n\n/**\n * Utility to check if current environment should skip authentication\n * Useful for development and testing\n */\nexport function shouldSkipAuth(): boolean {\n const skipAuth = process.env.SKIP_BLOG_PLATFORM_AUTH;\n return skipAuth === \"true\" || skipAuth === \"1\" || process.env.NODE_ENV === \"test\";\n}\n","/**\n * Rate limiting for blog platform API endpoints\n * \n * This implements rate limiting using Upstash Redis to prevent abuse\n * and ensure fair usage across all API consumers.\n */\n\nimport { Ratelimit } from \"@upstash/ratelimit\";\nimport { Redis } from \"@upstash/redis\";\nimport type { PublishResult } from \"@/types/contracts\";\n\n/**\n * Rate limit configuration interface\n * Allows customers to customize rate limiting behavior\n */\nexport interface RateLimitConfig {\n /** Upstash Redis REST URL */\n redisUrl: string;\n \n /** Upstash Redis REST token */\n redisToken: string;\n \n /** Requests per minute limit (default: 5) */\n requestsPerMinute?: number;\n \n /** Redis key prefix for rate limiting (default: \"blog-platform-ratelimit\") */\n keyPrefix?: string;\n \n /** Enable analytics (default: true) */\n analytics?: boolean;\n}\n\n/**\n * Rate limit result\n */\nexport interface RateLimitResult {\n /** Whether the request is allowed */\n success: boolean;\n \n /** Number of requests remaining in current window */\n remaining: number;\n \n /** When the rate limit window resets (Unix timestamp) */\n reset: number;\n \n /** Total requests allowed per window */\n limit: number;\n \n /** Current request count in window */\n count: number;\n}\n\n/**\n * Rate limiter instance\n */\ntype GlobalWithRateLimiter = typeof globalThis & {\n __BLOG_PLATFORM_RATE_LIMITER__?: Ratelimit | null;\n};\n\nfunction getRateLimiter(): Ratelimit | null {\n const globalRef = globalThis as GlobalWithRateLimiter;\n return globalRef.__BLOG_PLATFORM_RATE_LIMITER__ ?? null;\n}\n\nfunction setRateLimiter(instance: Ratelimit | null): void {\n const globalRef = globalThis as GlobalWithRateLimiter;\n globalRef.__BLOG_PLATFORM_RATE_LIMITER__ = instance;\n}\n\n/**\n * Configure the rate limiter\n * This must be called during app initialization\n */\nexport function configureRateLimit(config: RateLimitConfig): void {\n const {\n redisUrl,\n redisToken,\n requestsPerMinute = 5,\n keyPrefix = \"blog-platform-ratelimit\",\n analytics = true,\n } = config;\n\n const redis = new Redis({\n url: redisUrl,\n token: redisToken,\n });\n\n const limiter = new Ratelimit({\n redis,\n analytics,\n prefix: keyPrefix,\n // 5 requests per minute sliding window\n limiter: Ratelimit.slidingWindow(requestsPerMinute, \"1m\"),\n });\n\n setRateLimiter(limiter);\n}\n\n/**\n * Auto-configure rate limiting from environment variables\n * Uses UPSTASH_REDIS_REST_URL and UPSTASH_REDIS_REST_TOKEN\n */\nexport function autoConfigureRateLimit(): void {\n const redisUrl = process.env.UPSTASH_REDIS_REST_URL;\n const redisToken = process.env.UPSTASH_REDIS_REST_TOKEN;\n \n if (!redisUrl || !redisToken) {\n console.warn(\"Blog platform: No Upstash Redis configuration found. Rate limiting disabled.\");\n return;\n }\n \n configureRateLimit({\n redisUrl,\n redisToken,\n });\n \n console.log(\"Blog platform: Rate limiting configured (5 requests per minute per token)\");\n}\n\n/**\n * Check rate limit for a given identifier (typically an auth token)\n * @param identifier - Unique identifier (usually the authentication token)\n * @returns Rate limit result\n */\nexport async function checkRateLimit(identifier: string): Promise<RateLimitResult> {\n const limiter = getRateLimiter();\n if (!limiter) {\n // Rate limiting not configured - allow all requests\n console.warn(\"Blog platform: Rate limiter not configured. All requests allowed.\");\n return {\n success: true,\n remaining: 999,\n reset: Date.now() + 60000,\n limit: 5,\n count: 0,\n };\n }\n\n try {\n const result = await limiter.limit(identifier);\n \n return {\n success: result.success,\n remaining: result.remaining,\n reset: result.reset,\n limit: result.limit,\n count: result.limit - result.remaining,\n };\n } catch (error) {\n console.error(\"Blog platform: Rate limit check failed:\", error);\n // On error, allow the request but log the issue\n return {\n success: true,\n remaining: 0,\n reset: Date.now() + 60000,\n limit: 5,\n count: 0,\n };\n }\n}\n\n/**\n * Create a rate limit error response\n * @param rateLimitResult - The rate limit result that failed\n * @param idempotencyKey - Optional idempotency key from request\n * @returns PublishResult with rate limit error\n */\nexport function createRateLimitErrorResponse(\n rateLimitResult: RateLimitResult,\n idempotencyKey = \"\"\n): PublishResult {\n const resetMinutes = Math.ceil((rateLimitResult.reset - Date.now()) / 60000);\n \n return {\n success: false,\n error: {\n code: \"PUB011\",\n message: `Rate limit exceeded. You can make ${rateLimitResult.limit} requests per minute. Try again in ${resetMinutes} minute(s).`,\n details: {\n rateLimit: rateLimitResult,\n },\n },\n idempotencyKey,\n };\n}\n\n/**\n * Rate limiting middleware for API routes\n * @param identifier - Unique identifier for rate limiting (typically auth token)\n * @param idempotencyKey - Optional idempotency key from request\n * @returns Rate limit result or error response\n */\nexport async function enforceRateLimit(\n identifier: string,\n idempotencyKey = \"\"\n): Promise<{ allowed: true; rateLimitResult: RateLimitResult } | { allowed: false; errorResponse: PublishResult }> {\n const rateLimitResult = await checkRateLimit(identifier);\n \n if (!rateLimitResult.success) {\n return {\n allowed: false,\n errorResponse: createRateLimitErrorResponse(rateLimitResult, idempotencyKey),\n };\n }\n \n return {\n allowed: true,\n rateLimitResult,\n };\n}\n\n/**\n * Get rate limit headers for HTTP responses\n * @param rateLimitResult - Rate limit result\n * @returns Headers object for HTTP response\n */\nexport function getRateLimitHeaders(rateLimitResult: RateLimitResult): Record<string, string> {\n return {\n \"X-RateLimit-Limit\": rateLimitResult.limit.toString(),\n \"X-RateLimit-Remaining\": rateLimitResult.remaining.toString(),\n \"X-RateLimit-Reset\": rateLimitResult.reset.toString(),\n \"Retry-After\": Math.ceil((rateLimitResult.reset - Date.now()) / 1000).toString(),\n };\n}\n","/**\n * Initialization utilities for the blog platform package\n *\n * This module provides convenient setup functions for customers\n * to configure authentication, storage, and other platform features.\n */\n\nimport {\n setAuthConfig,\n type AuthConfig,\n NoAuth,\n EnvAuth,\n} from \"./auth\";\nimport { setStorage, type BlogPlatformStorage } from \"./database\";\nimport {\n autoConfigureRateLimit,\n configureRateLimit,\n type RateLimitConfig,\n} from \"./ratelimit\";\n\ndeclare global {\n // Using `var` here intentionally to declare a global on Node's globalThis\n // across module boundaries. This is not a directive; remove stale disable.\n var __BLOG_PLATFORM_INITIALISED__: boolean | undefined;\n}\n\n/**\n * Configuration options for blog platform initialization\n */\nexport interface BlogPlatformConfig {\n /** Authentication configuration (REQUIRED) */\n auth: AuthConfig;\n\n /** Custom storage implementation */\n storage?: BlogPlatformStorage;\n\n /** Custom rate limiting configuration */\n rateLimit?: RateLimitConfig;\n\n /** Whether to automatically configure rate limiting from environment */\n autoRateLimit?: boolean;\n}\n\n/**\n * Initialize the blog platform with custom configuration\n *\n * This should be called once during your app startup, typically in:\n * - Next.js: middleware.ts or layout.tsx\n * - Express: app startup\n * - Other frameworks: main entry point\n *\n * @param config - Configuration options (auth is REQUIRED)\n *\n * @example\n * ```typescript\n * // Environment-based API key authentication\n * initBlogPlatform({\n * auth: new EnvAuth(), // Reads from BLOG_PLATFORM_API_KEYS\n * });\n *\n * // Custom environment variable\n * initBlogPlatform({\n * auth: new EnvAuth(\"MY_BLOG_API_KEYS\"),\n * });\n *\n * // Custom authentication provider\n * initBlogPlatform({\n * auth: new CustomAuthProvider(),\n * storage: new PostgresStorage(connectionString),\n * rateLimit: {\n * redisUrl: \"https://...\",\n * redisToken: \"...\",\n * requestsPerMinute: 10\n * }\n * });\n *\n * // Disable rate limiting for testing\n * initBlogPlatform({\n * auth: new NoAuth(), // Development only!\n * autoRateLimit: false\n * });\n * ```\n */\nexport function initBlogPlatform(config: BlogPlatformConfig): void {\n const {\n auth,\n storage,\n rateLimit,\n autoRateLimit = true,\n } = config;\n\n // Validate required configuration\n if (!auth) {\n throw new Error(\n \"Blog platform initialization failed: 'auth' is required.\\n\" +\n \"Example: initBlogPlatform({ auth: new EnvAuth() })\\n\" +\n \"See https://github.com/xexr/blog-platform#authentication for more details.\"\n );\n }\n\n // Set up authentication (REQUIRED)\n console.log(\"Blog platform: Setting up authentication\");\n setAuthConfig(auth);\n\n // Set up rate limiting\n if (rateLimit) {\n console.log(\"Blog platform: Using custom rate limiting configuration\");\n configureRateLimit(rateLimit);\n } else if (autoRateLimit) {\n console.log(\n \"Blog platform: Auto-configuring rate limiting from environment\",\n );\n autoConfigureRateLimit();\n } else {\n console.log(\"Blog platform: Rate limiting disabled\");\n }\n\n // Set up storage\n if (storage) {\n console.log(\"Blog platform: Using custom storage provider\");\n setStorage(storage);\n } else {\n console.log(\n \"Blog platform: Using default in-memory storage (not suitable for production)\",\n );\n }\n\n console.log(\"Blog platform initialized successfully\");\n globalThis.__BLOG_PLATFORM_INITIALISED__ = true;\n}\n\n/**\n * Initialize the blog platform only once per process.\n * Safe to call from multiple modules (e.g., layout + API routes).\n *\n * @param config - Configuration options (auth is REQUIRED)\n */\nexport function initBlogPlatformOnce(config: BlogPlatformConfig): void {\n if (globalThis.__BLOG_PLATFORM_INITIALISED__) {\n console.log(\"Blog platform: Already initialized, skipping\");\n return;\n }\n console.log(\"Blog platform: Initializing blog platform once\");\n initBlogPlatform(config);\n}\n\n/**\n * Quick setup for development/testing\n * WARNING: Disables authentication - never use in production!\n * Uses NoAuth (accepts all requests), in-memory storage, and disables rate limiting\n */\nexport function initBlogPlatformDev(): void {\n initBlogPlatform({\n auth: new NoAuth(),\n autoRateLimit: false\n });\n console.log(\n \"Blog platform: Development mode enabled (no auth, in-memory storage, no rate limiting)\",\n );\n}\n\n/**\n * Production setup with environment-based API keys and rate limiting\n * Requires BLOG_PLATFORM_API_KEYS (or custom env var), UPSTASH_REDIS_REST_URL,\n * and UPSTASH_REDIS_REST_TOKEN environment variables\n *\n * @param apiKeysEnvVar - Optional custom environment variable name for API keys (default: BLOG_PLATFORM_API_KEYS)\n */\nexport function initBlogPlatformProd(apiKeysEnvVar?: string): void {\n const envVar = apiKeysEnvVar ?? \"BLOG_PLATFORM_API_KEYS\";\n\n if (!process.env[envVar]) {\n throw new Error(\n `Missing required environment variable: ${envVar}. ` +\n \"Set this to a comma-separated list of API keys for blog platform authentication.\",\n );\n }\n\n initBlogPlatform({\n auth: new EnvAuth(envVar),\n autoRateLimit: true,\n });\n console.log(\n \"Blog platform: Production mode enabled (environment-based auth, rate limiting)\",\n );\n}\n","import type { InferSelectModel } from \"drizzle-orm\";\nimport { and, desc, eq, sql } from \"drizzle-orm\";\nimport type { LibSQLDatabase } from \"drizzle-orm/libsql\";\nimport {\n sqliteTable,\n integer,\n text,\n uniqueIndex,\n} from \"drizzle-orm/sqlite-core\";\nimport type {\n PublishedArticle,\n PublishResult,\n PublishedAuthor,\n PublishedSite,\n} from \"../../types/contracts\";\nimport type { BlogPlatformStorage } from \"../database\";\n\n// Schema definitions for durable storage\nexport const bpArticles = sqliteTable(\n \"bp_articles\",\n {\n id: text(\"id\").primaryKey(),\n slug: text(\"slug\").notNull(),\n title: text(\"title\").notNull(),\n excerpt: text(\"excerpt\").notNull(),\n content: text(\"content\").notNull(),\n readingSeconds: integer(\"reading_seconds\").notNull(),\n wordCount: integer(\"word_count\").notNull(),\n publishedAt: text(\"published_at\").notNull(),\n updatedAt: text(\"updated_at\").notNull(),\n featuredImage: text(\"featured_image\"),\n featuredImageAlt: text(\"featured_image_alt\"),\n featuredImageCaption: text(\"featured_image_caption\"),\n featuredImageCreditText: text(\"featured_image_credit_text\"),\n featuredImageCreditUrl: text(\"featured_image_credit_url\"),\n // Store complex objects as JSON strings\n authorJson: text(\"author_json\"),\n siteJson: text(\"site_json\").notNull(),\n metaJson: text(\"meta_json\").notNull(),\n version: integer(\"version\").notNull(),\n },\n (table) => ({\n slugUniqueIdx: uniqueIndex(\"bp_articles_slug_unique\").on(table.slug),\n }),\n);\n\nexport const bpOperations = sqliteTable(\"bp_operations\", {\n key: text(\"key\").primaryKey(),\n // JSON-encoded PublishResult\n resultJson: text(\"result_json\").notNull(),\n createdAt: integer(\"created_at\", { mode: \"timestamp_ms\" }).notNull(),\n // Optional TTL field (not currently used by adapter logic)\n expiresAt: integer(\"expires_at\", { mode: \"timestamp_ms\" }),\n});\n\ntype ArticleRow = InferSelectModel<typeof bpArticles>;\n\nfunction toRow(article: PublishedArticle): ArticleRow {\n return {\n id: article.id,\n slug: article.slug,\n title: article.title,\n excerpt: article.excerpt,\n content: article.content,\n readingSeconds: article.readingSeconds,\n wordCount: article.wordCount,\n publishedAt: article.publishedAt,\n updatedAt: article.updatedAt,\n featuredImage: article.featuredImage ?? null,\n featuredImageAlt: article.featuredImageAlt ?? null,\n featuredImageCaption: article.featuredImageCaption ?? null,\n featuredImageCreditText: article.featuredImageCreditText ?? null,\n featuredImageCreditUrl: article.featuredImageCreditUrl ?? null,\n authorJson: article.author ? JSON.stringify(article.author) : null,\n siteJson: JSON.stringify(article.site),\n metaJson: JSON.stringify({\n ...article.meta,\n __bloggyTopics: article.topics ?? [],\n }),\n version: article.version,\n };\n}\n\nfunction fromRow(row: ArticleRow): PublishedArticle {\n return {\n id: row.id,\n slug: row.slug,\n title: row.title,\n excerpt: row.excerpt,\n content: row.content,\n readingSeconds: row.readingSeconds,\n wordCount: row.wordCount,\n publishedAt: row.publishedAt,\n updatedAt: row.updatedAt,\n featuredImage: row.featuredImage ?? undefined,\n featuredImageAlt: row.featuredImageAlt ?? undefined,\n featuredImageCaption: row.featuredImageCaption ?? undefined,\n featuredImageCreditText: row.featuredImageCreditText ?? undefined,\n featuredImageCreditUrl: row.featuredImageCreditUrl ?? undefined,\n author: row.authorJson\n ? (JSON.parse(row.authorJson) as PublishedAuthor)\n : null,\n site: JSON.parse(row.siteJson) as PublishedSite,\n topics: extractTopics(row.metaJson),\n meta: extractMeta(row.metaJson),\n version: row.version,\n };\n}\n\nfunction extractTopics(metaJson: string): PublishedArticle[\"topics\"] {\n const parsed = JSON.parse(metaJson) as PublishedArticle[\"meta\"] & {\n __bloggyTopics?: PublishedArticle[\"topics\"];\n };\n return parsed.__bloggyTopics ?? [];\n}\n\nfunction extractMeta(metaJson: string): PublishedArticle[\"meta\"] {\n const parsed = JSON.parse(metaJson) as PublishedArticle[\"meta\"] & {\n __bloggyTopics?: PublishedArticle[\"topics\"];\n };\n delete parsed.__bloggyTopics;\n const meta = parsed;\n return meta;\n}\n\nexport interface DrizzleStorageOptions {\n // Optional: limit retention for operations table (ms)\n operationTtlMs?: number;\n}\n\n/**\n * Drizzle-backed durable storage adapter.\n * Pass a Drizzle Database instance created with drizzle-orm/libsql.\n */\nexport class DrizzleStorage implements BlogPlatformStorage {\n private readonly db: LibSQLDatabase;\n private readonly options: DrizzleStorageOptions;\n\n constructor(db: LibSQLDatabase, options: DrizzleStorageOptions = {}) {\n this.db = db;\n this.options = options;\n }\n\n async saveArticle(\n article: PublishedArticle,\n idempotencyKey: string,\n ): Promise<PublishResult> {\n const existing = await this.checkIdempotency(idempotencyKey);\n\n // CRITICAL FIX: Allow republish after unpublish\n // If we found a cached operation result AND it was successful,\n // check if the article still exists. If it was removed (unpublished),\n // proceed with the save to allow republishing.\n if (existing) {\n if (existing.success) {\n // Check if article still exists in database\n const articleExists = await this.db\n .select({ id: bpArticles.id })\n .from(bpArticles)\n .where(eq(bpArticles.id, article.id))\n .limit(1);\n\n // If article was removed, allow republish by not returning cached result\n if (articleExists.length === 0) {\n // Article was unpublished - proceed with save\n } else {\n // Article still exists - this is a true duplicate\n return existing;\n }\n } else {\n // Failed operations are always returned as-is\n return existing;\n }\n }\n\n // Enforce slug uniqueness: if slug exists with a different article id → conflict\n const bySlug = await this.db\n .select()\n .from(bpArticles)\n .where(eq(bpArticles.slug, article.slug))\n .limit(1);\n\n const existingRow = bySlug[0];\n if (existingRow && existingRow.id !== article.id) {\n const conflict: PublishResult = {\n success: false,\n error: {\n code: \"PUB003\",\n message: \"This URL is already in use. Please choose another.\",\n },\n idempotencyKey,\n };\n await this.storeOperationResult(idempotencyKey, conflict);\n return conflict;\n }\n\n // Upsert by id; slug is immutable once set for a given id\n const row = toRow(article);\n\n if (bySlug.length === 0) {\n // Insert new\n await this.db.insert(bpArticles).values(row).run();\n } else {\n // Update existing row for same article id\n await this.db\n .update(bpArticles)\n .set({\n title: row.title,\n excerpt: row.excerpt,\n content: row.content,\n readingSeconds: row.readingSeconds,\n wordCount: row.wordCount,\n updatedAt: row.updatedAt,\n featuredImage: row.featuredImage,\n featuredImageAlt: row.featuredImageAlt,\n featuredImageCaption: row.featuredImageCaption,\n featuredImageCreditText: row.featuredImageCreditText,\n featuredImageCreditUrl: row.featuredImageCreditUrl,\n authorJson: row.authorJson,\n siteJson: row.siteJson,\n metaJson: row.metaJson,\n version: row.version,\n })\n .where(and(eq(bpArticles.id, row.id), eq(bpArticles.slug, row.slug)))\n .run();\n }\n\n const success: PublishResult = {\n success: true,\n url: `/${article.slug}`,\n platformPostId: article.id,\n publishedAt: article.publishedAt,\n idempotencyKey,\n };\n\n await this.storeOperationResult(idempotencyKey, success);\n return success;\n }\n\n async getArticle(slug: string): Promise<PublishedArticle | null> {\n const rows = await this.db\n .select()\n .from(bpArticles)\n .where(eq(bpArticles.slug, slug))\n .limit(1);\n if (!rows[0]) return null;\n return fromRow(rows[0]);\n }\n\n async listArticles(\n options: {\n limit?: number;\n offset?: number;\n sortBy?: \"publishedAt\" | \"updatedAt\";\n order?: \"asc\" | \"desc\";\n } = {},\n ): Promise<{ articles: PublishedArticle[]; total: number }> {\n const {\n limit = 10,\n offset = 0,\n sortBy = \"publishedAt\",\n order = \"desc\",\n } = options;\n const orderColumn =\n sortBy === \"publishedAt\" ? bpArticles.publishedAt : bpArticles.updatedAt;\n const orderBy = order === \"desc\" ? desc(orderColumn) : orderColumn;\n\n const items = await this.db\n .select()\n .from(bpArticles)\n .orderBy(orderBy)\n .limit(limit)\n .offset(offset);\n\n // Total count (approx via window-free query)\n const totalRow = await this.db\n .select({ c: sql<number>`count(*)` })\n .from(bpArticles);\n const total = Number(totalRow?.[0]?.c ?? 0);\n\n return { articles: items.map(fromRow), total };\n }\n\n async removeArticle(\n slug: string,\n idempotencyKey: string,\n ): Promise<PublishResult> {\n const existing = await this.checkIdempotency(idempotencyKey);\n\n // CRITICAL FIX: Allow re-unpublish after republish\n // If we found a cached operation result AND it was successful,\n // check if the article NOW exists. If it was republished,\n // proceed with the removal to allow re-unpublishing.\n if (existing) {\n if (existing.success) {\n // Check if article exists NOW (might have been republished)\n const articleExists = await this.db\n .select({ id: bpArticles.id })\n .from(bpArticles)\n .where(eq(bpArticles.slug, slug))\n .limit(1);\n\n // If article EXISTS, it was republished - allow re-unpublish\n if (articleExists.length > 0) {\n // Article was republished - proceed with removal\n } else {\n // Article still removed - this is a true duplicate\n return existing;\n }\n } else {\n // Failed operations are always returned as-is\n return existing;\n }\n }\n\n const found = await this.db\n .select()\n .from(bpArticles)\n .where(eq(bpArticles.slug, slug))\n .limit(1);\n if (!found[0]) {\n const notFound: PublishResult = {\n success: false,\n error: { code: \"PUB007\", message: \"Article not found\" },\n idempotencyKey,\n };\n await this.storeOperationResult(idempotencyKey, notFound);\n return notFound;\n }\n\n await this.db.delete(bpArticles).where(eq(bpArticles.slug, slug)).run();\n\n const result: PublishResult = { success: true, idempotencyKey };\n await this.storeOperationResult(idempotencyKey, result);\n return result;\n }\n\n async checkIdempotency(\n idempotencyKey: string,\n ): Promise<PublishResult | null> {\n const rows = await this.db\n .select()\n .from(bpOperations)\n .where(eq(bpOperations.key, idempotencyKey))\n .limit(1);\n if (!rows[0]) return null;\n try {\n return JSON.parse(rows[0].resultJson) as PublishResult;\n } catch {\n return null;\n }\n }\n\n async storeOperationResult(\n idempotencyKey: string,\n result: PublishResult,\n ): Promise<void> {\n const now = Date.now();\n const expiresAt = this.options.operationTtlMs\n ? now + this.options.operationTtlMs\n : null;\n // Upsert behavior using ON CONFLICT is not portable via builder; rely on delete+insert\n await this.db\n .delete(bpOperations)\n .where(eq(bpOperations.key, idempotencyKey))\n .run();\n await this.db\n .insert(bpOperations)\n .values({\n key: idempotencyKey,\n resultJson: JSON.stringify(result),\n createdAt: new Date(now),\n expiresAt: expiresAt ? new Date(expiresAt) : null,\n })\n .run();\n }\n}\n\n/**\n * Helper: Return SQL strings for creating required tables.\n * Consumers can embed these in their migrations.\n */\nexport function getDrizzleAdapterSql(): {\n createArticles: string;\n createOperations: string;\n} {\n return {\n createArticles: `CREATE TABLE IF NOT EXISTS bp_articles (\n id TEXT PRIMARY KEY,\n slug TEXT NOT NULL UNIQUE,\n title TEXT NOT NULL,\n excerpt TEXT NOT NULL,\n content TEXT NOT NULL,\n reading_seconds INTEGER NOT NULL,\n word_count INTEGER NOT NULL,\n published_at TEXT NOT NULL,\n updated_at TEXT NOT NULL,\n featured_image TEXT,\n featured_image_alt TEXT,\n featured_image_caption TEXT,\n featured_image_credit_text TEXT,\n featured_image_credit_url TEXT,\n author_json TEXT,\n site_json TEXT NOT NULL,\n meta_json TEXT NOT NULL,\n version INTEGER NOT NULL\n);`,\n createOperations: `CREATE TABLE IF NOT EXISTS bp_operations (\n key TEXT PRIMARY KEY,\n result_json TEXT NOT NULL,\n created_at INTEGER NOT NULL,\n expires_at INTEGER\n);`,\n };\n}\n","/**\n * SEO utilities for canonical URL generation and validation.\n *\n * These utilities ensure proper canonical URL structure for SEO optimization,\n * preventing duplicate content issues and improving search engine indexing.\n */\n\nimport type { PublishedArticle, PublishedSite } from '../types/contracts';\n\n/**\n * Configuration options for canonical URL generation.\n */\nexport interface CanonicalUrlOptions {\n /** Whether to force HTTPS protocol (default: true) */\n forceHttps?: boolean;\n\n /** Whether to remove trailing slashes (default: true) */\n removeTrailingSlash?: boolean;\n\n /** Custom domain override (uses site.domain if not provided) */\n domain?: string;\n\n /** Custom path prefix (default: '/blog') */\n pathPrefix?: string;\n}\n\n/**\n * Normalizes a domain by ensuring proper protocol and removing trailing slashes.\n *\n * @param domain - The domain to normalize\n * @param forceHttps - Whether to force HTTPS protocol\n * @returns The normalized domain\n *\n * @example\n * ```typescript\n * normalizeDomain('example.com') // 'https://example.com'\n * normalizeDomain('http://example.com/') // 'https://example.com'\n * normalizeDomain('https://example.com', false) // 'https://example.com'\n * ```\n */\nexport function normalizeDomain(domain: string, forceHttps = true): string {\n let normalized = domain.trim();\n\n // Remove trailing slashes\n normalized = normalized.replace(/\\/+$/, '');\n\n // Add protocol if missing\n if (!/^https?:\\/\\//.exec(normalized)) {\n normalized = `${forceHttps ? 'https' : 'http'}://${normalized}`;\n }\n\n // Force HTTPS if requested\n if (forceHttps && normalized.startsWith('http://')) {\n normalized = normalized.replace('http://', 'https://');\n }\n\n return normalized;\n}\n\n/**\n * Validates and normalizes a slug for URL usage.\n *\n * @param slug - The slug to validate and normalize\n * @returns The normalized slug\n * @throws Error if slug is invalid\n *\n * @example\n * ```typescript\n * normalizeSlug('hello-world') // 'hello-world'\n * normalizeSlug('Hello World!') // throws Error\n * normalizeSlug('hello--world') // 'hello-world'\n * ```\n */\nexport function normalizeSlug(slug: string): string {\n const trimmed = slug.trim();\n\n if (!trimmed) {\n throw new Error('Slug cannot be empty');\n }\n\n // Check if slug contains only valid characters\n if (!/^[a-z0-9-]+$/.test(trimmed)) {\n throw new Error('Slug can only contain lowercase letters, numbers, and hyphens');\n }\n\n // Remove multiple consecutive hyphens\n const normalized = trimmed.replace(/-+/g, '-');\n\n // Remove leading/trailing hyphens\n const clean = normalized.replace(/^-+|-+$/g, '');\n\n if (!clean) {\n throw new Error('Slug cannot consist only of hyphens');\n }\n\n return clean;\n}\n\n/**\n * Generates a canonical URL for an article.\n *\n * @param article - The published article\n * @param options - Configuration options for URL generation\n * @returns The canonical URL\n * @throws Error if article or site data is invalid\n *\n * @example\n * ```typescript\n * const article = {\n * slug: 'hello-world',\n * site: { domain: 'example.com' },\n * // ... other fields\n * };\n *\n * generateCanonicalUrl(article)\n * // 'https://example.com/blog/hello-world'\n *\n * generateCanonicalUrl(article, { pathPrefix: '/posts' })\n * // 'https://example.com/posts/hello-world'\n * ```\n */\nexport function generateCanonicalUrl(\n article: PublishedArticle,\n options: CanonicalUrlOptions = {}\n): string {\n const {\n forceHttps = true,\n removeTrailingSlash = true,\n domain = article.site.domain,\n pathPrefix = '/blog'\n } = options;\n\n if (!domain) {\n throw new Error('Domain is required for canonical URL generation');\n }\n\n if (!article.slug) {\n throw new Error('Article slug is required for canonical URL generation');\n }\n\n // Validate and normalize inputs\n const normalizedDomain = normalizeDomain(domain, forceHttps);\n const normalizedSlug = normalizeSlug(article.slug);\n\n // Ensure path prefix starts with '/' and doesn't end with '/'\n const cleanPrefix = pathPrefix\n .replace(/^(?!\\/)/, '/') // Add leading slash if missing\n .replace(/\\/+$/, ''); // Remove trailing slashes\n\n // Construct the canonical URL\n let canonicalUrl = `${normalizedDomain}${cleanPrefix}/${normalizedSlug}`;\n\n // Remove trailing slash if requested\n if (removeTrailingSlash) {\n canonicalUrl = canonicalUrl.replace(/\\/+$/, '');\n }\n\n return canonicalUrl;\n}\n\n/**\n * Generates a canonical URL for an article from site and slug data.\n * Useful when you don't have a full PublishedArticle object.\n *\n * @param site - The published site\n * @param slug - The article slug\n * @param options - Configuration options for URL generation\n * @returns The canonical URL\n *\n * @example\n * ```typescript\n * const site = { domain: 'example.com', ... };\n * generateCanonicalUrlFromSlug(site, 'hello-world')\n * // 'https://example.com/blog/hello-world'\n * ```\n */\nexport function generateCanonicalUrlFromSlug(\n site: PublishedSite,\n slug: string,\n options: CanonicalUrlOptions = {}\n): string {\n return generateCanonicalUrl(\n {\n slug,\n site,\n // Minimal required fields for canonical URL generation\n id: '',\n title: '',\n excerpt: '',\n content: '',\n readingSeconds: 0,\n wordCount: 0,\n publishedAt: '',\n updatedAt: '',\n author: null,\n meta: { keywords: [] },\n version: 1\n },\n options\n );\n}\n\n/**\n * Validates if a URL is a valid canonical URL format.\n *\n * @param url - The URL to validate\n * @returns True if the URL is valid for canonical use\n *\n * @example\n * ```typescript\n * isValidCanonicalUrl('https://example.com/blog/hello-world') // true\n * isValidCanonicalUrl('http://example.com/blog/hello-world') // true\n * isValidCanonicalUrl('example.com/blog/hello-world') // false (missing protocol)\n * isValidCanonicalUrl('https://example.com/blog/hello world') // false (spaces)\n * ```\n */\nexport function isValidCanonicalUrl(url: string): boolean {\n try {\n const parsed = new URL(url);\n\n // Must be HTTP or HTTPS\n if (!['http:', 'https:'].includes(parsed.protocol)) {\n return false;\n }\n\n // Must have a valid hostname (not empty or just slashes)\n if (!parsed.hostname || parsed.hostname.length === 0) {\n return false;\n }\n\n // Check for URLs with empty hostname like 'https:///path'\n if (/^https?:\\/\\/\\//.exec(url) && !/^https?:\\/\\/[^\\/]/.exec(url)) {\n return false;\n }\n\n // Path should not contain unencoded spaces or other problematic characters\n // Check the original URL string since URL constructor auto-encodes\n if (url.includes(' ')) {\n return false;\n }\n\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Extracts the base URL (protocol + hostname + port) from a canonical URL.\n *\n * @param canonicalUrl - The canonical URL\n * @returns The base URL\n *\n * @example\n * ```typescript\n * getBaseUrl('https://example.com/blog/hello-world') // 'https://example.com'\n * getBaseUrl('https://blog.example.com:8080/posts/test') // 'https://blog.example.com:8080'\n * ```\n */\nexport function getBaseUrl(canonicalUrl: string): string {\n try {\n const parsed = new URL(canonicalUrl);\n return `${parsed.protocol}//${parsed.host}`;\n } catch {\n throw new Error('Invalid canonical URL provided');\n }\n}\n\n/**\n * Updates an article's canonical URL in its meta field.\n *\n * @param article - The article to update\n * @param options - Configuration options for URL generation\n * @returns A new article object with updated canonical URL\n *\n * @example\n * ```typescript\n * const updatedArticle = updateArticleCanonicalUrl(article);\n * console.log(updatedArticle.meta.canonicalUrl); // Generated canonical URL\n * ```\n */\nexport function updateArticleCanonicalUrl(\n article: PublishedArticle,\n options: CanonicalUrlOptions = {}\n): PublishedArticle {\n const canonicalUrl = generateCanonicalUrl(article, options);\n\n return {\n ...article,\n meta: {\n ...article.meta,\n canonicalUrl\n }\n };\n}","/**\n * Metadata generation utilities for SEO meta tags, OpenGraph, and Twitter Cards.\n *\n * These utilities create comprehensive metadata for blog articles and pages,\n * optimizing for search engines and social media sharing platforms.\n */\n\nimport type { PublishedArticle, PublishedSite } from '../types/contracts';\nimport { generateCanonicalUrl, type CanonicalUrlOptions } from './seo';\n\n/**\n * Configuration options for metadata generation.\n */\nexport interface MetadataOptions {\n /** Canonical URL generation options */\n canonical?: CanonicalUrlOptions;\n\n /** OpenGraph configuration */\n openGraph?: {\n /** Site name for OpenGraph */\n siteName?: string;\n /** Default OpenGraph image URL */\n defaultImage?: string;\n /** OpenGraph locale (defaults to site locale) */\n locale?: string;\n /** OpenGraph type (defaults to 'article') */\n type?: 'article' | 'website';\n };\n\n /** Twitter Card configuration */\n twitter?: {\n /** Twitter site handle (e.g., '@blogname') */\n site?: string;\n /** Twitter creator handle (e.g., '@authorname') */\n creator?: string;\n /** Default Twitter card type */\n cardType?: 'summary' | 'summary_large_image' | 'app' | 'player';\n };\n\n /** Additional meta tag configuration */\n meta?: {\n /** Robots meta tag directive */\n robots?: string;\n /** Viewport meta tag content */\n viewport?: string;\n /** Theme color for mobile browsers */\n themeColor?: string;\n /** Application name */\n applicationName?: string;\n };\n}\n\n/**\n * Generated metadata for HTML head section.\n */\nexport interface GeneratedMetadata {\n /** Basic HTML meta tags */\n meta: MetaTag[];\n\n /** OpenGraph meta tags */\n openGraph: MetaTag[];\n\n /** Twitter Card meta tags */\n twitter: MetaTag[];\n\n /** Link tags (canonical, etc.) */\n links: LinkTag[];\n\n /** Title tag content */\n title: string;\n\n /** Meta description content */\n description: string;\n\n /** Canonical URL */\n canonicalUrl: string;\n}\n\n/**\n * HTML meta tag representation.\n */\nexport interface MetaTag {\n name?: string;\n property?: string;\n content: string;\n httpEquiv?: string;\n}\n\n/**\n * HTML link tag representation.\n */\nexport interface LinkTag {\n rel: string;\n href: string;\n type?: string;\n title?: string;\n}\n\n/**\n * Generates comprehensive metadata for an article page.\n *\n * @param article - The published article\n * @param options - Metadata generation options\n * @returns Complete metadata for HTML head section\n *\n * @example\n * ```typescript\n * const metadata = generateArticleMetadata(article, {\n * openGraph: {\n * siteName: 'My Blog',\n * defaultImage: 'https://example.com/og-default.jpg'\n * },\n * twitter: {\n * site: '@myblog',\n * cardType: 'summary_large_image'\n * }\n * });\n * ```\n */\nexport function generateArticleMetadata(\n article: PublishedArticle,\n options: MetadataOptions = {}\n): GeneratedMetadata {\n const canonicalUrl = generateCanonicalUrl(article, options.canonical);\n const title = article.meta.title ?? article.title;\n const description = article.meta.description ?? article.excerpt;\n const siteName = options.openGraph?.siteName ?? article.site.name;\n\n // Basic meta tags\n const meta: MetaTag[] = [\n { name: 'description', content: description },\n { name: 'keywords', content: article.meta.keywords.join(', ') },\n { name: 'author', content: article.author?.name ?? siteName },\n { name: 'published_time', content: article.publishedAt },\n { name: 'modified_time', content: article.updatedAt },\n { name: 'article:reading_time', content: Math.ceil(article.readingSeconds / 60).toString() },\n ];\n\n // Add robots meta if specified\n if (options.meta?.robots) {\n meta.push({ name: 'robots', content: options.meta.robots });\n }\n\n // Add viewport meta if specified\n if (options.meta?.viewport) {\n meta.push({ name: 'viewport', content: options.meta.viewport });\n }\n\n // Add theme color if specified\n if (options.meta?.themeColor) {\n meta.push({ name: 'theme-color', content: options.meta.themeColor });\n }\n\n // Add application name if specified\n if (options.meta?.applicationName) {\n meta.push({ name: 'application-name', content: options.meta.applicationName });\n }\n\n // Generate OpenGraph metadata\n const openGraph = generateOpenGraphMetadata(article, canonicalUrl, {\n siteName,\n defaultImage: options.openGraph?.defaultImage,\n locale: options.openGraph?.locale ?? article.site.locale,\n type: options.openGraph?.type ?? 'article',\n });\n\n // Generate Twitter Card metadata\n const twitter = generateTwitterCardMetadata(article, {\n site: options.twitter?.site,\n creator: options.twitter?.creator,\n cardType: options.twitter?.cardType ?? 'summary_large_image',\n });\n\n // Generate link tags\n const links: LinkTag[] = [\n { rel: 'canonical', href: canonicalUrl },\n ];\n\n return {\n meta,\n openGraph,\n twitter,\n links,\n title,\n description,\n canonicalUrl,\n };\n}\n\n/**\n * Generates metadata for a blog home page or listing page.\n *\n * @param site - The published site information\n * @param options - Metadata generation options\n * @param pageInfo - Optional page-specific information\n * @returns Complete metadata for HTML head section\n *\n * @example\n * ```typescript\n * const metadata = generateSiteMetadata(site, {\n * openGraph: {\n * defaultImage: 'https://example.com/og-home.jpg'\n * }\n * }, {\n * title: 'Latest Articles',\n * description: 'Browse our latest blog posts',\n * path: '/blog'\n * });\n * ```\n */\nexport function generateSiteMetadata(\n site: PublishedSite,\n options: MetadataOptions = {},\n pageInfo?: {\n title?: string;\n description?: string;\n path?: string;\n pageNumber?: number;\n }\n): GeneratedMetadata {\n const path = pageInfo?.path ?? '/blog';\n const domain = options.canonical?.domain ?? site.domain;\n const canonicalUrl = `https://${domain}${path}`;\n\n const title = pageInfo?.title\n ? `${pageInfo.title} | ${site.name}`\n : site.name;\n\n const description = pageInfo?.description ?? site.description;\n const siteName = options.openGraph?.siteName ?? site.name;\n\n // Basic meta tags\n const meta: MetaTag[] = [\n { name: 'description', content: description },\n { name: 'author', content: siteName },\n ];\n\n // Add page number for pagination\n if (pageInfo?.pageNumber && pageInfo.pageNumber > 1) {\n meta.push({ name: 'page', content: pageInfo.pageNumber.toString() });\n }\n\n // Add robots meta if specified\n if (options.meta?.robots) {\n meta.push({ name: 'robots', content: options.meta.robots });\n }\n\n // Add viewport meta if specified\n if (options.meta?.viewport) {\n meta.push({ name: 'viewport', content: options.meta.viewport });\n }\n\n // Add theme color if specified\n if (options.meta?.themeColor) {\n meta.push({ name: 'theme-color', content: options.meta.themeColor });\n }\n\n // Add application name if specified\n if (options.meta?.applicationName) {\n meta.push({ name: 'application-name', content: options.meta.applicationName });\n }\n\n // Generate OpenGraph metadata for site\n const openGraph: MetaTag[] = [\n { property: 'og:title', content: title },\n { property: 'og:description', content: description },\n { property: 'og:url', content: canonicalUrl },\n { property: 'og:site_name', content: siteName },\n { property: 'og:locale', content: options.openGraph?.locale ?? site.locale },\n { property: 'og:type', content: options.openGraph?.type ?? 'website' },\n ];\n\n // Add default OpenGraph image if provided\n if (options.openGraph?.defaultImage) {\n openGraph.push(\n { property: 'og:image', content: options.openGraph.defaultImage },\n { property: 'og:image:alt', content: `${siteName} - ${site.tagline}` }\n );\n }\n\n // Generate Twitter Card metadata\n const twitter = generateTwitterCardMetadata(\n null, // No article for site pages\n {\n site: options.twitter?.site,\n creator: options.twitter?.creator,\n cardType: options.twitter?.cardType ?? 'summary',\n },\n {\n title,\n description,\n image: options.openGraph?.defaultImage,\n }\n );\n\n // Generate link tags\n const links: LinkTag[] = [\n { rel: 'canonical', href: canonicalUrl },\n ];\n\n return {\n meta,\n openGraph,\n twitter,\n links,\n title,\n description,\n canonicalUrl,\n };\n}\n\n/**\n * Generates OpenGraph metadata for an article.\n */\nfunction generateOpenGraphMetadata(\n article: PublishedArticle,\n canonicalUrl: string,\n options: {\n siteName: string;\n defaultImage?: string;\n locale: string;\n type: string;\n }\n): MetaTag[] {\n const title = article.meta.title ?? article.title;\n const description = article.meta.description ?? article.excerpt;\n const image = article.meta.ogImage ?? article.featuredImage ?? options.defaultImage;\n\n const openGraph: MetaTag[] = [\n { property: 'og:title', content: title },\n { property: 'og:description', content: description },\n { property: 'og:url', content: canonicalUrl },\n { property: 'og:site_name', content: options.siteName },\n { property: 'og:locale', content: options.locale },\n { property: 'og:type', content: options.type },\n { property: 'article:published_time', content: article.publishedAt },\n { property: 'article:modified_time', content: article.updatedAt },\n ];\n\n // Add image if available\n if (image) {\n const imageAlt = article.featuredImageAlt ?? `${article.title} - ${options.siteName}`;\n openGraph.push(\n { property: 'og:image', content: image },\n { property: 'og:image:alt', content: imageAlt }\n );\n }\n\n // Add author information\n if (article.author) {\n openGraph.push({ property: 'article:author', content: article.author.name });\n\n // Add author profile URL if we can construct one\n if (article.author.slug) {\n const authorUrl = canonicalUrl.replace(/\\/[^/]+$/, `/authors/${article.author.slug}`);\n openGraph.push({ property: 'article:author:url', content: authorUrl });\n }\n }\n\n // Add article tags from keywords\n article.meta.keywords.forEach(keyword => {\n openGraph.push({ property: 'article:tag', content: keyword });\n });\n\n // Add reading time\n const readingMinutes = Math.ceil(article.readingSeconds / 60);\n openGraph.push({ property: 'article:reading_time', content: readingMinutes.toString() });\n\n return openGraph;\n}\n\n/**\n * Generates Twitter Card metadata.\n */\nfunction generateTwitterCardMetadata(\n article: PublishedArticle | null,\n options: {\n site?: string;\n creator?: string;\n cardType: string;\n },\n overrides?: {\n title?: string;\n description?: string;\n image?: string;\n }\n): MetaTag[] {\n const title = overrides?.title ?? article?.meta.title ?? article?.title ?? '';\n const description = overrides?.description ?? article?.meta.description ?? article?.excerpt ?? '';\n const image = overrides?.image ?? article?.meta.ogImage ?? article?.featuredImage;\n\n const twitter: MetaTag[] = [\n { name: 'twitter:card', content: options.cardType },\n { name: 'twitter:title', content: title },\n { name: 'twitter:description', content: description },\n ];\n\n // Add site handle if provided\n if (options.site) {\n twitter.push({ name: 'twitter:site', content: options.site });\n }\n\n // Add creator handle if provided (for articles) or from options\n if (article?.author && options.creator) {\n twitter.push({ name: 'twitter:creator', content: options.creator });\n } else if (options.creator) {\n twitter.push({ name: 'twitter:creator', content: options.creator });\n }\n\n // Add image if available\n if (image) {\n twitter.push({ name: 'twitter:image', content: image });\n\n if (article?.featuredImageAlt) {\n twitter.push({ name: 'twitter:image:alt', content: article.featuredImageAlt });\n }\n }\n\n return twitter;\n}\n\n/**\n * Converts metadata to HTML string for server-side rendering.\n *\n * @param metadata - Generated metadata object\n * @returns HTML string for head section\n *\n * @example\n * ```typescript\n * const metadata = generateArticleMetadata(article);\n * const htmlHead = metadataToHtml(metadata);\n * // Use in server-side rendering\n * ```\n */\nexport function metadataToHtml(metadata: GeneratedMetadata): string {\n const elements: string[] = [];\n\n // Title\n elements.push(`<title>${escapeHtml(metadata.title)}</title>`);\n\n // Meta tags\n metadata.meta.forEach(tag => {\n const attrs: string[] = [];\n\n if (tag.name) attrs.push(`name=\"${escapeHtml(tag.name)}\"`);\n if (tag.property) attrs.push(`property=\"${escapeHtml(tag.property)}\"`);\n if (tag.httpEquiv) attrs.push(`http-equiv=\"${escapeHtml(tag.httpEquiv)}\"`);\n attrs.push(`content=\"${escapeHtml(tag.content)}\"`);\n\n elements.push(`<meta ${attrs.join(' ')} />`);\n });\n\n // OpenGraph tags\n metadata.openGraph.forEach(tag => {\n elements.push(`<meta property=\"${escapeHtml(tag.property!)}\" content=\"${escapeHtml(tag.content)}\" />`);\n });\n\n // Twitter tags\n metadata.twitter.forEach(tag => {\n elements.push(`<meta name=\"${escapeHtml(tag.name!)}\" content=\"${escapeHtml(tag.content)}\" />`);\n });\n\n // Link tags\n metadata.links.forEach(link => {\n const attrs: string[] = [];\n attrs.push(`rel=\"${escapeHtml(link.rel)}\"`);\n attrs.push(`href=\"${escapeHtml(link.href)}\"`);\n if (link.type) attrs.push(`type=\"${escapeHtml(link.type)}\"`);\n if (link.title) attrs.push(`title=\"${escapeHtml(link.title)}\"`);\n\n elements.push(`<link ${attrs.join(' ')} />`);\n });\n\n return elements.join('\\n');\n}\n\n/**\n * Escapes HTML special characters for safe inclusion in HTML attributes.\n */\nfunction escapeHtml(text: string): string {\n const htmlEscapes: Record<string, string> = {\n '&': '&amp;',\n '<': '&lt;',\n '>': '&gt;',\n '\"': '&quot;',\n \"'\": '&#x27;',\n };\n\n return text.replace(/[&<>\"']/g, char => htmlEscapes[char] ?? char);\n}\n\n/**\n * Validates that metadata meets SEO best practices.\n *\n * @param metadata - Generated metadata to validate\n * @returns Validation results with warnings and errors\n *\n * @example\n * ```typescript\n * const metadata = generateArticleMetadata(article);\n * const validation = validateMetadata(metadata);\n *\n * if (validation.errors.length > 0) {\n * console.error('Metadata errors:', validation.errors);\n * }\n * ```\n */\nexport function validateMetadata(metadata: GeneratedMetadata): {\n valid: boolean;\n errors: string[];\n warnings: string[];\n} {\n const errors: string[] = [];\n const warnings: string[] = [];\n\n // Title validation\n if (!metadata.title) {\n errors.push('Title is required');\n } else if (metadata.title.length > 60) {\n warnings.push('Title longer than 60 characters may be truncated in search results');\n } else if (metadata.title.length < 30) {\n warnings.push('Title shorter than 30 characters may not be descriptive enough');\n }\n\n // Description validation\n if (!metadata.description) {\n errors.push('Meta description is required');\n } else if (metadata.description.length > 160) {\n warnings.push('Meta description longer than 160 characters may be truncated');\n } else if (metadata.description.length < 120) {\n warnings.push('Meta description shorter than 120 characters may not be descriptive enough');\n }\n\n // Canonical URL validation\n if (!metadata.canonicalUrl) {\n errors.push('Canonical URL is required');\n } else if (!metadata.canonicalUrl.startsWith('https://')) {\n warnings.push('Canonical URL should use HTTPS for better SEO');\n }\n\n // OpenGraph validation\n const ogImage = metadata.openGraph.find(tag => tag.property === 'og:image');\n if (!ogImage) {\n warnings.push('OpenGraph image missing - social media sharing will not show image preview');\n }\n\n // Twitter Card validation\n const twitterCard = metadata.twitter.find(tag => tag.name === 'twitter:card');\n if (!twitterCard) {\n warnings.push('Twitter Card type missing - Twitter sharing may not display properly');\n }\n\n return {\n valid: errors.length === 0,\n errors,\n warnings,\n };\n}","/**\n * Next.js-compatible sitemap generation utilities for blog platform integration.\n *\n * These utilities generate sitemap entries that follow Next.js MetadataRoute.Sitemap\n * conventions, allowing seamless integration with existing Next.js applications.\n *\n * @example Integration with existing Next.js sitemap:\n * ```typescript\n * // app/sitemap.ts\n * import { generateBlogSitemapEntries } from '@xexr/blog-platform';\n * import type { MetadataRoute } from 'next';\n *\n * export default async function sitemap(): Promise<MetadataRoute.Sitemap> {\n * // Your existing routes\n * const staticRoutes = [\n * { url: 'https://yoursite.com', lastModified: new Date(), priority: 1 },\n * { url: 'https://yoursite.com/about', lastModified: new Date(), priority: 0.8 }\n * ];\n *\n * // Blog platform entries\n * const blogEntries = await generateBlogSitemapEntries(blogConfig);\n *\n * return [...staticRoutes, ...blogEntries];\n * }\n * ```\n */\n\nimport type {\n PublishedArticle,\n PublishedSite,\n PublishedAuthor,\n} from \"../types/contracts\";\nimport {\n generateCanonicalUrl,\n normalizeDomain,\n type CanonicalUrlOptions,\n} from \"./seo\";\nimport { buildAuthorPath } from \"./urls\";\n\n/**\n * Configuration options for sitemap generation.\n */\nexport interface SitemapOptions {\n /** Canonical URL configuration */\n canonical?: CanonicalUrlOptions;\n\n /** Whether to include author pages in sitemap */\n includeAuthorPages?: boolean;\n\n /** Whether to include pagination pages in sitemap */\n includePaginationPages?: boolean;\n\n /** Number of articles per page for pagination calculation */\n articlesPerPage?: number;\n\n /** Maximum number of sitemap entries (defaults to 50,000 per Google guidelines) */\n maxEntries?: number;\n\n /** Change frequency for different page types */\n changeFrequency?: {\n /** Change frequency for blog home page */\n homePage?: SitemapChangeFreq;\n /** Change frequency for article pages */\n articles?: SitemapChangeFreq;\n /** Change frequency for author pages */\n authorPages?: SitemapChangeFreq;\n /** Change frequency for pagination pages */\n paginationPages?: SitemapChangeFreq;\n };\n\n /** Priority values for different page types */\n priority?: {\n /** Priority for blog home page (0.0-1.0) */\n homePage?: number;\n /** Priority for article pages (0.0-1.0) */\n articles?: number;\n /** Priority for author pages (0.0-1.0) */\n authorPages?: number;\n /** Priority for pagination pages (0.0-1.0) */\n paginationPages?: number;\n };\n}\n\n/**\n * Valid sitemap change frequency values as per XML sitemap standard.\n */\nexport type SitemapChangeFreq =\n | \"always\"\n | \"hourly\"\n | \"daily\"\n | \"weekly\"\n | \"monthly\"\n | \"yearly\"\n | \"never\";\n\n/**\n * Next.js MetadataRoute.Sitemap compatible entry.\n * This matches the expected format for Next.js sitemap generation.\n */\nexport interface NextjsSitemapEntry {\n /** The URL of the page */\n url: string;\n\n /** Last modification date */\n lastModified?: string | Date;\n\n /** Change frequency hint for search engines */\n changeFrequency?: SitemapChangeFreq;\n\n /** Priority relative to other URLs on the site (0.0-1.0) */\n priority?: number;\n\n /** Alternate language versions (for i18n) */\n alternates?: {\n languages?: Record<string, string>;\n };\n}\n\n/**\n * Legacy XML sitemap entry format (for backward compatibility).\n * @deprecated Use NextjsSitemapEntry for new implementations\n */\nexport interface SitemapEntry {\n /** The URL of the page */\n loc: string;\n\n /** Last modification date as ISO 8601 string */\n lastmod?: string;\n\n /** Change frequency hint for search engines */\n changefreq?: SitemapChangeFreq;\n\n /** Priority relative to other URLs on the site (0.0-1.0) */\n priority?: number;\n}\n\n/**\n * Complete sitemap data structure.\n */\nexport interface SitemapData {\n /** All URL entries in the sitemap */\n entries: SitemapEntry[];\n\n /** Total number of entries */\n totalEntries: number;\n\n /** Whether the sitemap was truncated due to size limits */\n truncated: boolean;\n\n /** Generation timestamp */\n generatedAt: string;\n\n /** Base URL used for canonical URL generation */\n baseUrl: string;\n}\n\n/**\n * Generates Next.js-compatible sitemap entries for blog platform integration.\n *\n * @param site - The published site information\n * @param articles - Array of published articles\n * @param authors - Array of published authors (optional)\n * @param options - Sitemap generation options\n * @returns Array of Next.js MetadataRoute.Sitemap compatible entries\n *\n * @example\n * ```typescript\n * // In your Next.js app/sitemap.ts file:\n * import { generateBlogSitemapEntries } from '@xexr/blog-platform';\n * import type { MetadataRoute } from 'next';\n *\n * export default async function sitemap(): Promise<MetadataRoute.Sitemap> {\n * const blogEntries = await generateBlogSitemapEntries(site, articles, authors, {\n * includeAuthorPages: true,\n * includePaginationPages: true,\n * changeFrequency: { articles: 'monthly' }\n * });\n *\n * return [\n * // Your existing site routes\n * { url: 'https://yoursite.com', lastModified: new Date(), priority: 1 },\n * { url: 'https://yoursite.com/about', lastModified: new Date() },\n * // Blog entries\n * ...blogEntries\n * ];\n * }\n * ```\n */\nexport async function generateBlogSitemapEntries(\n site: PublishedSite,\n articles: readonly PublishedArticle[],\n authors: readonly PublishedAuthor[] = [],\n options: SitemapOptions = {},\n): Promise<NextjsSitemapEntry[]> {\n const {\n includeAuthorPages = true,\n includePaginationPages = true,\n articlesPerPage = 10,\n maxEntries = 50000,\n changeFrequency = {},\n priority = {},\n } = options;\n\n const entries: NextjsSitemapEntry[] = [];\n const baseUrl = normalizeDomain(\n options.canonical?.domain ?? site.domain,\n options.canonical?.forceHttps ?? true,\n );\n\n const pathPrefix = options.canonical?.pathPrefix ?? \"/blog\";\n\n // Add blog home page\n entries.push({\n url: `${baseUrl}${pathPrefix}`,\n lastModified: getLatestModificationDate(articles),\n changeFrequency: changeFrequency.homePage ?? \"daily\",\n priority: priority.homePage ?? 1.0,\n });\n\n // Add individual article pages\n articles.forEach((article) => {\n if (entries.length >= maxEntries) return;\n\n const articleUrl = generateCanonicalUrl(article, options.canonical);\n entries.push({\n url: articleUrl,\n lastModified: article.updatedAt,\n changeFrequency: changeFrequency.articles ?? \"monthly\",\n priority: priority.articles ?? 0.8,\n });\n });\n\n // Add author pages if enabled\n if (includeAuthorPages) {\n authors.forEach((author) => {\n if (entries.length >= maxEntries) return;\n\n const authorUrl = `${baseUrl}${buildAuthorPath(pathPrefix, author.slug)}`;\n\n // Find the latest article by this author for lastModified\n const authorArticles = articles.filter(\n (article) => article.author?.id === author.id,\n );\n const latestAuthorMod = getLatestModificationDate(authorArticles);\n\n entries.push({\n url: authorUrl,\n lastModified: latestAuthorMod,\n changeFrequency: changeFrequency.authorPages ?? \"weekly\",\n priority: priority.authorPages ?? 0.6,\n });\n });\n }\n\n // Add pagination pages if enabled\n if (includePaginationPages && articles.length > articlesPerPage) {\n const totalPages = Math.ceil(articles.length / articlesPerPage);\n\n for (let page = 2; page <= totalPages; page++) {\n if (entries.length >= maxEntries) break;\n\n entries.push({\n url: `${baseUrl}${pathPrefix}?page=${page}`,\n lastModified: getLatestModificationDate(articles),\n changeFrequency: changeFrequency.paginationPages ?? \"daily\",\n priority: priority.paginationPages ?? 0.5,\n });\n }\n }\n\n return entries;\n}\n\n/**\n * Legacy sitemap generation for backward compatibility.\n * @deprecated Use generateBlogSitemapEntries for Next.js integration\n *\n * @param site - The published site information\n * @param articles - Array of published articles\n * @param authors - Array of published authors (optional)\n * @param options - Sitemap generation options\n * @returns Complete sitemap data\n */\nexport function generateSitemap(\n site: PublishedSite,\n articles: readonly PublishedArticle[],\n authors: readonly PublishedAuthor[] = [],\n options: SitemapOptions = {},\n): SitemapData {\n const {\n includeAuthorPages = true,\n includePaginationPages = true,\n articlesPerPage = 10,\n maxEntries = 50000,\n changeFrequency = {},\n priority = {},\n } = options;\n\n const entries: SitemapEntry[] = [];\n const baseUrl = normalizeDomain(\n options.canonical?.domain ?? site.domain,\n options.canonical?.forceHttps ?? true,\n );\n\n const pathPrefix = options.canonical?.pathPrefix ?? \"/blog\";\n const generatedAt = new Date().toISOString();\n\n // Calculate total potential entries to determine if truncation will occur\n let potentialEntries = 1; // Home page\n potentialEntries += articles.length; // Article pages\n if (includeAuthorPages) {\n potentialEntries += authors.length; // Author pages\n }\n if (includePaginationPages && articles.length > articlesPerPage) {\n const totalPages = Math.ceil(articles.length / articlesPerPage);\n potentialEntries += totalPages - 1; // Pagination pages (excluding page 1 which is home)\n }\n\n const willTruncate = potentialEntries > maxEntries;\n\n // Add blog home page\n entries.push({\n loc: `${baseUrl}${pathPrefix}`,\n lastmod: getLatestModificationDate(articles),\n changefreq: changeFrequency.homePage ?? \"daily\",\n priority: priority.homePage ?? 1.0,\n });\n\n // Add individual article pages\n articles.forEach((article) => {\n if (entries.length >= maxEntries) return;\n\n const articleUrl = generateCanonicalUrl(article, options.canonical);\n entries.push({\n loc: articleUrl,\n lastmod: article.updatedAt,\n changefreq: changeFrequency.articles ?? \"monthly\",\n priority: priority.articles ?? 0.8,\n });\n });\n\n // Add author pages if enabled\n if (includeAuthorPages) {\n authors.forEach((author) => {\n if (entries.length >= maxEntries) return;\n\n const authorUrl = `${baseUrl}${buildAuthorPath(pathPrefix, author.slug)}`;\n\n // Find the latest article by this author for lastmod\n const authorArticles = articles.filter(\n (article) => article.author?.id === author.id,\n );\n const latestAuthorMod = getLatestModificationDate(authorArticles);\n\n entries.push({\n loc: authorUrl,\n lastmod: latestAuthorMod,\n changefreq: changeFrequency.authorPages ?? \"weekly\",\n priority: priority.authorPages ?? 0.6,\n });\n });\n }\n\n // Add pagination pages if enabled\n if (includePaginationPages && articles.length > articlesPerPage) {\n const totalPages = Math.ceil(articles.length / articlesPerPage);\n\n for (let page = 2; page <= totalPages; page++) {\n if (entries.length >= maxEntries) break;\n\n entries.push({\n loc: `${baseUrl}${pathPrefix}?page=${page}`,\n lastmod: getLatestModificationDate(articles),\n changefreq: changeFrequency.paginationPages ?? \"daily\",\n priority: priority.paginationPages ?? 0.5,\n });\n }\n }\n\n return {\n entries,\n totalEntries: entries.length,\n truncated: willTruncate,\n generatedAt,\n baseUrl,\n };\n}\n\n/**\n * Converts sitemap data to XML format.\n *\n * @param sitemapData - The sitemap data to convert\n * @returns XML string in sitemap format\n *\n * @example\n * ```typescript\n * const sitemap = generateSitemap(site, articles);\n * const xmlString = sitemapToXml(sitemap);\n * // Use in API route response\n * ```\n */\nexport function sitemapToXml(sitemapData: SitemapData): string {\n const xmlHeader = '<?xml version=\"1.0\" encoding=\"UTF-8\"?>';\n const urlsetOpen =\n '<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">';\n const urlsetClose = \"</urlset>\";\n\n const urlEntries = sitemapData.entries.map((entry) => {\n const elements: string[] = [];\n\n elements.push(` <url>`);\n elements.push(` <loc>${escapeXml(entry.loc)}</loc>`);\n\n if (entry.lastmod) {\n elements.push(` <lastmod>${escapeXml(entry.lastmod)}</lastmod>`);\n }\n\n if (entry.changefreq) {\n elements.push(\n ` <changefreq>${escapeXml(entry.changefreq)}</changefreq>`,\n );\n }\n\n if (entry.priority !== undefined) {\n elements.push(` <priority>${entry.priority.toFixed(1)}</priority>`);\n }\n\n elements.push(` </url>`);\n\n return elements.join(\"\\n\");\n });\n\n return [xmlHeader, urlsetOpen, ...urlEntries, urlsetClose].join(\"\\n\");\n}\n\n/**\n * Generates a sitemap index for large blogs that need multiple sitemaps.\n *\n * @param sitemaps - Array of sitemap information\n * @param baseUrl - Base URL for the site\n * @returns XML string for sitemap index\n *\n * @example\n * ```typescript\n * const sitemapIndex = generateSitemapIndex([\n * { url: 'https://example.com/sitemap-articles.xml', lastmod: '2023-01-01T00:00:00Z' },\n * { url: 'https://example.com/sitemap-authors.xml', lastmod: '2023-01-01T00:00:00Z' }\n * ], 'https://example.com');\n * ```\n */\nexport function generateSitemapIndex(\n sitemaps: readonly { url: string; lastmod?: string }[],\n _baseUrl: string,\n): string {\n const xmlHeader = '<?xml version=\"1.0\" encoding=\"UTF-8\"?>';\n const indexOpen =\n '<sitemapindex xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">';\n const indexClose = \"</sitemapindex>\";\n\n const sitemapEntries = sitemaps.map((sitemap) => {\n const elements: string[] = [];\n\n elements.push(` <sitemap>`);\n elements.push(` <loc>${escapeXml(sitemap.url)}</loc>`);\n\n if (sitemap.lastmod) {\n elements.push(` <lastmod>${escapeXml(sitemap.lastmod)}</lastmod>`);\n }\n\n elements.push(` </sitemap>`);\n\n return elements.join(\"\\n\");\n });\n\n return [xmlHeader, indexOpen, ...sitemapEntries, indexClose].join(\"\\n\");\n}\n\n/**\n * Validates sitemap data for compliance with search engine guidelines.\n *\n * @param sitemapData - The sitemap data to validate\n * @returns Validation results with errors and warnings\n *\n * @example\n * ```typescript\n * const sitemap = generateSitemap(site, articles);\n * const validation = validateSitemap(sitemap);\n *\n * if (validation.errors.length > 0) {\n * console.error('Sitemap errors:', validation.errors);\n * }\n * ```\n */\nexport function validateSitemap(sitemapData: SitemapData): {\n valid: boolean;\n errors: string[];\n warnings: string[];\n} {\n const errors: string[] = [];\n const warnings: string[] = [];\n\n // Check entry count\n if (sitemapData.entries.length === 0) {\n errors.push(\"Sitemap must contain at least one URL\");\n } else if (sitemapData.entries.length > 50000) {\n errors.push(\"Sitemap contains more than 50,000 URLs (Google limit)\");\n }\n\n // Check for truncation\n if (sitemapData.truncated) {\n warnings.push(\"Sitemap was truncated due to size limits\");\n }\n\n // Validate individual entries\n sitemapData.entries.forEach((entry, index) => {\n // Validate URL format\n try {\n new URL(entry.loc);\n } catch {\n errors.push(`Invalid URL at entry ${index + 1}: ${entry.loc}`);\n }\n\n // Validate priority range\n if (\n entry.priority !== undefined &&\n (entry.priority < 0 || entry.priority > 1)\n ) {\n errors.push(\n `Invalid priority at entry ${index + 1}: must be between 0.0 and 1.0`,\n );\n }\n\n // Validate lastmod format\n if (entry.lastmod && !isValidISODate(entry.lastmod)) {\n errors.push(\n `Invalid lastmod date at entry ${index + 1}: ${entry.lastmod}`,\n );\n }\n\n // Check URL length (Google limit is 2048 characters)\n if (entry.loc.length > 2048) {\n warnings.push(`URL at entry ${index + 1} exceeds 2048 character limit`);\n }\n });\n\n // Check for duplicate URLs\n const urlCounts = new Map<string, number>();\n sitemapData.entries.forEach((entry) => {\n const count = urlCounts.get(entry.loc) ?? 0;\n urlCounts.set(entry.loc, count + 1);\n });\n\n urlCounts.forEach((count, url) => {\n if (count > 1) {\n errors.push(`Duplicate URL found: ${url} (appears ${count} times)`);\n }\n });\n\n return {\n valid: errors.length === 0,\n errors,\n warnings,\n };\n}\n\n/**\n * Gets the latest modification date from an array of articles.\n */\nfunction getLatestModificationDate(\n articles: readonly PublishedArticle[],\n): string {\n if (articles.length === 0) {\n return new Date().toISOString();\n }\n\n const latestDate = articles.reduce((latest, article) => {\n const articleDate = new Date(article.updatedAt);\n return articleDate > latest ? articleDate : latest;\n }, new Date(articles[0]!.updatedAt));\n\n return latestDate.toISOString();\n}\n\n/**\n * Creates a separate sitemap specifically for blog content.\n * Useful for large sites that need to split sitemaps by content type.\n *\n * @param site - The published site information\n * @param articles - Array of published articles\n * @param authors - Array of published authors (optional)\n * @param options - Sitemap generation options\n * @returns Next.js sitemap function\n *\n * @example\n * ```typescript\n * // app/blog-sitemap/route.ts - separate blog sitemap endpoint\n * import { createBlogSitemapRoute } from '@xexr/blog-platform';\n *\n * export const GET = createBlogSitemapRoute(site, articles, authors, {\n * includeAuthorPages: true,\n * articlesPerPage: 20\n * });\n * ```\n */\nexport function createBlogSitemapRoute(\n site: PublishedSite,\n articles: readonly PublishedArticle[],\n authors: readonly PublishedAuthor[] = [],\n options: SitemapOptions = {},\n) {\n return async function GET() {\n const entries = await generateBlogSitemapEntries(\n site,\n articles,\n authors,\n options,\n );\n\n // Convert to Next.js sitemap format and return as XML\n const xmlEntries = entries.map((entry) => ({\n loc: entry.url,\n lastmod:\n typeof entry.lastModified === \"string\"\n ? entry.lastModified\n : entry.lastModified?.toISOString(),\n changefreq: entry.changeFrequency,\n priority: entry.priority,\n }));\n\n const sitemapData = {\n entries: xmlEntries,\n totalEntries: xmlEntries.length,\n truncated: false,\n generatedAt: new Date().toISOString(),\n baseUrl: normalizeDomain(\n options.canonical?.domain ?? site.domain,\n options.canonical?.forceHttps ?? true,\n ),\n };\n\n const xml = sitemapToXml(sitemapData);\n\n return new Response(xml, {\n headers: {\n \"Content-Type\": \"application/xml\",\n \"Cache-Control\": \"public, max-age=3600, s-maxage=3600\",\n },\n });\n };\n}\n\n/**\n * Configuration interface for blog data fetching.\n * Used to fetch blog data for sitemap generation.\n */\nexport interface BlogSitemapConfig {\n /** Function to fetch site data */\n getSite: () => Promise<PublishedSite>;\n\n /** Function to fetch published articles */\n getArticles: () => Promise<readonly PublishedArticle[]>;\n\n /** Function to fetch authors (optional) */\n getAuthors?: () => Promise<readonly PublishedAuthor[]>;\n\n /** Sitemap generation options */\n options?: SitemapOptions;\n}\n\n/**\n * Higher-order function that creates a Next.js sitemap function with data fetching.\n * Ideal for dynamic blog content that needs to be fetched at sitemap generation time.\n *\n * @param config - Configuration for fetching blog data\n * @returns Next.js sitemap function\n *\n * @example\n * ```typescript\n * // app/sitemap.ts\n * import { createDynamicBlogSitemap } from '@xexr/blog-platform';\n * import { getBlogData } from './lib/blog';\n *\n * export default createDynamicBlogSitemap({\n * getSite: () => getBlogData().site,\n * getArticles: () => getBlogData().articles,\n * getAuthors: () => getBlogData().authors,\n * options: {\n * includeAuthorPages: true,\n * changeFrequency: { articles: 'weekly' }\n * }\n * });\n * ```\n */\nexport function createDynamicBlogSitemap(config: BlogSitemapConfig) {\n return async function sitemap(): Promise<NextjsSitemapEntry[]> {\n const site = await config.getSite();\n const articles = await config.getArticles();\n const authors = config.getAuthors ? await config.getAuthors() : [];\n\n return generateBlogSitemapEntries(site, articles, authors, config.options);\n };\n}\n\n/**\n * Escapes special XML characters for safe inclusion in XML content.\n */\nfunction escapeXml(text: string): string {\n const xmlEscapes: Record<string, string> = {\n \"&\": \"&amp;\",\n \"<\": \"&lt;\",\n \">\": \"&gt;\",\n '\"': \"&quot;\",\n \"'\": \"&#x27;\",\n };\n\n return text.replace(/[&<>\"']/g, (char) => xmlEscapes[char] ?? char);\n}\n\n/**\n * Validates if a string is a valid ISO 8601 date.\n */\nfunction isValidISODate(dateString: string): boolean {\n try {\n const date = new Date(dateString);\n const isoString = date.toISOString();\n\n // Handle both formats: with and without milliseconds\n // 2023-01-01T00:00:00.000Z and 2023-01-01T00:00:00Z are both valid\n const normalizedInput =\n dateString.endsWith(\"Z\") && !dateString.includes(\".\")\n ? dateString.replace(\"Z\", \".000Z\")\n : dateString;\n\n return isoString === normalizedInput && !isNaN(date.getTime());\n } catch {\n return false;\n }\n}\n","{\n \"name\": \"@xexr/blog-platform\",\n \"version\": \"1.0.11\",\n \"description\": \"SEO-friendly blog platform for Next.js 15 with Bloggy integration\",\n \"main\": \"./dist/index.js\",\n \"types\": \"./dist/index.d.ts\",\n \"exports\": {\n \".\": {\n \"types\": \"./dist/index.d.ts\",\n \"import\": \"./dist/index.mjs\",\n \"require\": \"./dist/index.js\"\n },\n \"./types\": {\n \"types\": \"./dist/types/index.d.ts\",\n \"import\": \"./dist/types/index.mjs\",\n \"require\": \"./dist/types/index.js\"\n },\n \"./app/blog/page\": {\n \"types\": \"./dist/app/blog/page.d.ts\",\n \"import\": \"./dist/app/blog/page.tsx\",\n \"default\": \"./dist/app/blog/page.tsx\"\n },\n \"./app/blog/[slug]/page\": {\n \"types\": \"./dist/app/blog/[slug]/page.d.ts\",\n \"import\": \"./dist/app/blog/[slug]/page.tsx\",\n \"default\": \"./dist/app/blog/[slug]/page.tsx\"\n },\n \"./app/*\": \"./dist/app/*\",\n \"./styles/*\": \"./dist/styles/*\"\n },\n \"files\": [\n \"dist/**/*\",\n \"README.md\",\n \"LICENSE\",\n \"CHANGELOG.md\"\n ],\n \"license\": \"MIT\",\n \"scripts\": {\n \"build\": \"tsup && node scripts/copy-dist-assets.mjs\",\n \"test\": \"vitest\",\n \"lint\": \"eslint src --max-warnings 0\",\n \"typecheck\": \"tsc --noEmit\",\n \"prepublishOnly\": \"pnpm run build\"\n },\n \"peerDependencies\": {\n \"@libsql/client\": \"^0.15.0\",\n \"drizzle-orm\": \"^0.44.0\",\n \"next\": \"^15.0.0 || ^16.0.0\",\n \"react\": \"^18.0.0 || ^19.0.0\",\n \"react-dom\": \"^18.0.0 || ^19.0.0\"\n },\n \"dependencies\": {\n \"@radix-ui/react-separator\": \"^1.1.8\",\n \"@radix-ui/react-slot\": \"^1.2.4\",\n \"@upstash/ratelimit\": \"^2.0.8\",\n \"@upstash/redis\": \"^1.37.0\",\n \"class-variance-authority\": \"^0.7.1\",\n \"clsx\": \"^2.1.1\",\n \"date-fns\": \"^4.1.0\",\n \"lucide-react\": \"^1.11.0\",\n \"next-mdx-remote-client\": \"^2.1.10\",\n \"react-icons\": \"^5.6.0\",\n \"rehype-slug\": \"^6.0.0\",\n \"remark-gfm\": \"^4.0.1\",\n \"remark-toc\": \"^9.0.0\",\n \"tailwind-merge\": \"^3.5.0\"\n },\n \"devDependencies\": {\n \"@types/react\": \"19.2.14\",\n \"tsup\": \"^8.5.1\",\n \"typescript\": \"^5.9.3\",\n \"vitest\": \"^4.1.5\"\n }\n}\n","// Import package.json for version info (works with resolveJsonModule)\nimport packageJson from \"../../package.json\";\n\n/**\n * Version information\n */\nexport interface VersionInfo {\n name: string;\n version: string;\n major: number;\n minor: number;\n patch: number;\n}\n\n/**\n * Version compatibility result\n */\nexport interface VersionCompatibilityResult {\n compatible: boolean;\n errorCode?: string;\n errorMessage?: string;\n warning?: string;\n}\n\n/**\n * Version compatibility error codes (matches PRD error codes)\n */\nexport const VERSION_ERROR_CODES = {\n PUB009: \"Major version incompatibility\",\n PUB010: \"Minor version warning\",\n} as const;\n\n/**\n * Parse semantic version string into components\n * @param version - Version string (e.g., \"1.2.3\")\n * @returns Parsed version components\n */\nfunction parseVersion(version: string): { major: number; minor: number; patch: number } {\n const cleaned = version.replace(/^v/, \"\"); // Remove 'v' prefix if present\n const parts = cleaned.split(\".\");\n \n if (parts.length < 3) {\n throw new Error(`Invalid version format: ${version}`);\n }\n \n const major = parseInt(parts[0] ?? \"0\", 10);\n const minor = parseInt(parts[1] ?? \"0\", 10);\n const patch = parseInt(parts[2]?.split(\"-\")[0] ?? \"0\", 10); // Handle pre-release versions\n \n if (isNaN(major) || isNaN(minor) || isNaN(patch)) {\n throw new Error(`Invalid version format: ${version}`);\n }\n \n return { major, minor, patch };\n}\n\n/**\n * Get blog platform package version (current package)\n * @returns Blog platform version information\n */\nexport function getBlogPlatformVersion(): VersionInfo {\n // Use imported package.json (works reliably in both CJS and ESM)\n const versionComponents = parseVersion(packageJson.version);\n\n return {\n name: packageJson.name,\n version: packageJson.version,\n ...versionComponents,\n };\n}\n\n/**\n * Parse version header from incoming request\n * Expected format: \"bloggy/1.0.0 platform/1.0.0\"\n * @param headerValue - Version header value\n * @returns Parsed version information or null if invalid\n */\nexport function parseVersionHeader(headerValue: string): {\n bloggyVersion?: VersionInfo;\n platformVersion?: VersionInfo;\n} | null {\n try {\n const parts = headerValue.split(\" \");\n const result: { bloggyVersion?: VersionInfo; platformVersion?: VersionInfo } = {};\n \n for (const part of parts) {\n const [name, version] = part.split(\"/\");\n if (!name || !version) continue;\n \n const versionComponents = parseVersion(version);\n const versionInfo: VersionInfo = {\n name: name,\n version: version,\n ...versionComponents,\n };\n \n if (name === \"bloggy\") {\n result.bloggyVersion = versionInfo;\n } else if (name === \"platform\") {\n result.platformVersion = versionInfo;\n }\n }\n \n return result;\n } catch {\n return null;\n }\n}\n\n/**\n * Check version compatibility between two versions\n * Based on semantic versioning rules:\n * - Major version differences are incompatible (PUB009)\n * - Minor version differences are warnings (PUB010)\n * - Patch version differences are acceptable\n * \n * @param version1 - First version\n * @param version2 - Second version\n * @returns Compatibility result\n */\nexport function checkVersionCompatibility(\n version1: VersionInfo,\n version2: VersionInfo,\n): VersionCompatibilityResult {\n try {\n // Major version incompatibility\n if (version1.major !== version2.major) {\n return {\n compatible: false,\n errorCode: \"PUB009\",\n errorMessage: `Major version incompatibility: ${version1.name} ${version1.version} is not compatible with ${version2.name} ${version2.version}. Please upgrade.`,\n };\n }\n \n // Minor version warning\n if (version1.minor !== version2.minor) {\n return {\n compatible: true,\n errorCode: \"PUB010\",\n warning: `Minor version difference: ${version1.name} ${version1.version} with ${version2.name} ${version2.version}. Some features may not be available.`,\n };\n }\n \n // Compatible (same major.minor, patch differences are okay)\n return {\n compatible: true,\n };\n } catch (error) {\n return {\n compatible: false,\n errorMessage: `Failed to check version compatibility: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n };\n }\n}","/**\n * Security headers for blog platform API endpoints\n *\n * This provides comprehensive security headers to protect against common\n * web vulnerabilities including XSS, clickjacking, and content injection.\n */\n\nimport type { NextRequest } from \"next/server\";\n\n/**\n * Security headers configuration interface\n */\nexport interface SecurityConfig {\n /** Enable Content Security Policy (default: true) */\n enableCSP?: boolean;\n\n /** Custom CSP directives (merges with defaults) */\n cspDirectives?: Record<string, string>;\n\n /** Enable X-Frame-Options (default: true) */\n enableFrameOptions?: boolean;\n\n /** X-Frame-Options value (default: \"DENY\") */\n frameOptions?: string;\n\n /** Enable X-Content-Type-Options (default: true) */\n enableContentTypeOptions?: boolean;\n\n /** Enable X-XSS-Protection (default: true) */\n enableXSSProtection?: boolean;\n\n /** Enable Referrer-Policy (default: true) */\n enableReferrerPolicy?: boolean;\n\n /** Referrer policy value (default: \"strict-origin-when-cross-origin\") */\n referrerPolicy?: string;\n\n /** Enable Strict-Transport-Security for HTTPS (default: true) */\n enableHSTS?: boolean;\n\n /** HSTS max-age in seconds (default: 31536000 = 1 year) */\n hstsMaxAge?: number;\n\n /** Include HSTS subdomains (default: true) */\n hstsIncludeSubdomains?: boolean;\n\n /** Enable Permissions-Policy (default: true) */\n enablePermissionsPolicy?: boolean;\n\n /** Custom permissions policy directives */\n permissionsPolicyDirectives?: Record<string, string>;\n}\n\n/**\n * Default security configuration for blog platform APIs\n */\nconst DEFAULT_SECURITY_CONFIG: Required<SecurityConfig> = {\n enableCSP: true,\n cspDirectives: {\n \"default-src\": \"'self'\",\n \"script-src\": \"'self' 'unsafe-inline'\", // Allow inline scripts for API responses\n \"style-src\": \"'self' 'unsafe-inline'\", // Allow inline styles for blog rendering\n \"img-src\": \"'self' data: https:\", // Allow images from self, data URIs, and HTTPS\n \"font-src\": \"'self' https:\", // Allow fonts from self and HTTPS\n \"connect-src\": \"'self'\", // API connections to same origin\n \"media-src\": \"'self'\", // Media from same origin only\n \"object-src\": \"'none'\", // Disable object/embed elements\n \"base-uri\": \"'self'\", // Restrict base URIs to same origin\n \"form-action\": \"'self'\", // Forms can only submit to same origin\n \"frame-ancestors\": \"'none'\", // Prevent embedding in frames\n \"upgrade-insecure-requests\": \"\", // Upgrade HTTP to HTTPS\n },\n enableFrameOptions: true,\n frameOptions: \"DENY\",\n enableContentTypeOptions: true,\n enableXSSProtection: true,\n enableReferrerPolicy: true,\n referrerPolicy: \"strict-origin-when-cross-origin\",\n enableHSTS: true,\n hstsMaxAge: 31536000, // 1 year\n hstsIncludeSubdomains: true,\n enablePermissionsPolicy: true,\n permissionsPolicyDirectives: {\n \"camera\": \"()\", // Disable camera access\n \"microphone\": \"()\", // Disable microphone access\n \"geolocation\": \"()\", // Disable geolocation\n \"payment\": \"()\", // Disable payment API\n \"usb\": \"()\", // Disable USB access\n \"accelerometer\": \"()\", // Disable accelerometer\n \"gyroscope\": \"()\", // Disable gyroscope\n \"magnetometer\": \"()\", // Disable magnetometer\n },\n};\n\n/**\n * Get security configuration from environment or defaults\n */\nfunction getSecurityConfig(): Required<SecurityConfig> {\n const envCSPDisabled = process.env.BLOG_PLATFORM_DISABLE_CSP === \"true\";\n const envFrameOptions = process.env.BLOG_PLATFORM_FRAME_OPTIONS;\n const envHSTSDisabled = process.env.BLOG_PLATFORM_DISABLE_HSTS === \"true\";\n\n return {\n ...DEFAULT_SECURITY_CONFIG,\n enableCSP: !envCSPDisabled,\n frameOptions: envFrameOptions ?? DEFAULT_SECURITY_CONFIG.frameOptions,\n enableHSTS: !envHSTSDisabled,\n };\n}\n\n/**\n * Build Content Security Policy header value\n */\nfunction buildCSPHeader(directives: Record<string, string>): string {\n return Object.entries(directives)\n .map(([directive, value]) =>\n value ? `${directive} ${value}` : directive\n )\n .join(\"; \");\n}\n\n/**\n * Build Permissions Policy header value\n */\nfunction buildPermissionsPolicyHeader(directives: Record<string, string>): string {\n return Object.entries(directives)\n .map(([feature, allowlist]) => `${feature}=${allowlist}`)\n .join(\", \");\n}\n\n/**\n * Get security headers for HTTP responses\n */\nexport function getSecurityHeaders(\n request: NextRequest,\n config: SecurityConfig = {}\n): Record<string, string> {\n const securityConfig = { ...getSecurityConfig(), ...config };\n const headers: Record<string, string> = {};\n\n // Content Security Policy\n if (securityConfig.enableCSP) {\n const cspDirectives = {\n ...securityConfig.cspDirectives,\n ...(config.cspDirectives ?? {}),\n };\n headers[\"Content-Security-Policy\"] = buildCSPHeader(cspDirectives);\n }\n\n // X-Frame-Options (prevent clickjacking)\n if (securityConfig.enableFrameOptions) {\n headers[\"X-Frame-Options\"] = securityConfig.frameOptions;\n }\n\n // X-Content-Type-Options (prevent MIME sniffing)\n if (securityConfig.enableContentTypeOptions) {\n headers[\"X-Content-Type-Options\"] = \"nosniff\";\n }\n\n // X-XSS-Protection (legacy XSS protection)\n if (securityConfig.enableXSSProtection) {\n headers[\"X-XSS-Protection\"] = \"1; mode=block\";\n }\n\n // Referrer-Policy (control referrer information)\n if (securityConfig.enableReferrerPolicy) {\n headers[\"Referrer-Policy\"] = securityConfig.referrerPolicy;\n }\n\n // Strict-Transport-Security (HTTPS enforcement)\n if (securityConfig.enableHSTS && isHTTPS(request)) {\n const hstsValue = [\n `max-age=${securityConfig.hstsMaxAge}`,\n securityConfig.hstsIncludeSubdomains ? \"includeSubDomains\" : \"\",\n ].filter(Boolean).join(\"; \");\n\n headers[\"Strict-Transport-Security\"] = hstsValue;\n }\n\n // Permissions-Policy (feature control)\n if (securityConfig.enablePermissionsPolicy) {\n const permissionsDirectives = {\n ...securityConfig.permissionsPolicyDirectives,\n ...(config.permissionsPolicyDirectives ?? {}),\n };\n headers[\"Permissions-Policy\"] = buildPermissionsPolicyHeader(permissionsDirectives);\n }\n\n return headers;\n}\n\n/**\n * Check if request is over HTTPS\n */\nfunction isHTTPS(request: NextRequest): boolean {\n // Check protocol from URL\n if (request.url.startsWith(\"https://\")) {\n return true;\n }\n\n // Check forwarded protocol headers (for proxies/load balancers)\n const forwardedProto = request.headers.get(\"x-forwarded-proto\");\n if (forwardedProto === \"https\") {\n return true;\n }\n\n // Check if we're in a secure context (Cloudflare, Vercel, etc.)\n const cfVisitor = request.headers.get(\"cf-visitor\");\n if (cfVisitor?.includes('\"scheme\":\"https\"')) {\n return true;\n }\n\n return false;\n}\n\n/**\n * Create security headers optimized for API endpoints\n */\nexport function getAPISecurityHeaders(\n request: NextRequest,\n config: SecurityConfig = {}\n): Record<string, string> {\n // API-specific CSP that's less restrictive for JSON responses\n const apiCSPDirectives = {\n \"default-src\": \"'none'\", // APIs don't need default sources\n \"frame-ancestors\": \"'none'\", // Prevent embedding\n \"base-uri\": \"'none'\", // No base URI needed for APIs\n };\n\n return getSecurityHeaders(request, {\n ...config,\n cspDirectives: {\n ...apiCSPDirectives,\n ...(config.cspDirectives ?? {}),\n },\n });\n}\n\n/**\n * Create security headers optimized for blog pages\n */\nexport function getBlogSecurityHeaders(\n request: NextRequest,\n config: SecurityConfig = {}\n): Record<string, string> {\n // Blog-specific CSP that allows images, fonts, and styles\n const blogCSPDirectives = {\n \"default-src\": \"'self'\",\n \"script-src\": \"'self' 'unsafe-inline'\",\n \"style-src\": \"'self' 'unsafe-inline' https:\",\n \"img-src\": \"'self' data: https:\",\n \"font-src\": \"'self' https:\",\n \"connect-src\": \"'self'\",\n \"frame-src\": \"'none'\", // No iframes in blog posts\n \"object-src\": \"'none'\", // No plugins/objects\n };\n\n return getSecurityHeaders(request, {\n ...config,\n frameOptions: \"SAMEORIGIN\", // Allow embedding from same origin\n cspDirectives: {\n ...blogCSPDirectives,\n ...(config.cspDirectives ?? {}),\n },\n });\n}\n\n/**\n * Security header presets for different use cases\n */\nexport const SECURITY_PRESETS = {\n /** Strict security for API endpoints */\n API: {\n enableCSP: true,\n frameOptions: \"DENY\",\n cspDirectives: {\n \"default-src\": \"'none'\",\n \"frame-ancestors\": \"'none'\",\n \"base-uri\": \"'none'\",\n },\n },\n\n /** Balanced security for blog pages */\n BLOG: {\n enableCSP: true,\n frameOptions: \"SAMEORIGIN\",\n cspDirectives: {\n \"default-src\": \"'self'\",\n \"script-src\": \"'self' 'unsafe-inline'\",\n \"style-src\": \"'self' 'unsafe-inline' https:\",\n \"img-src\": \"'self' data: https:\",\n \"font-src\": \"'self' https:\",\n },\n },\n\n /** Development-friendly settings */\n DEVELOPMENT: {\n enableCSP: false,\n enableHSTS: false,\n frameOptions: \"SAMEORIGIN\",\n },\n} as const;\n\n/**\n * Validate and sanitize CSP directive values\n */\nexport function sanitizeCSPDirective(directive: string, value: string): string {\n // Remove potentially dangerous values\n const sanitized = value\n .replace(/javascript:/gi, \"\") // Remove javascript: URIs\n .replace(/data:/gi, \"data:\") // Normalize data: URIs\n .replace(/\\s+/g, \" \") // Normalize whitespace\n .trim();\n\n // Validate that value doesn't contain injection attempts\n if (sanitized.includes(\";\") || sanitized.includes(\"\\n\") || sanitized.includes(\"\\r\")) {\n console.warn(`Potentially dangerous CSP value for ${directive}: ${value}`);\n return \"'none'\"; // Safe fallback\n }\n\n return sanitized;\n}","/**\n * CORS configuration for blog platform API endpoints\n * \n * This provides centralized CORS handling with security best practices\n * for cross-origin requests from Bloggy core applications.\n */\n\nimport type { NextRequest } from \"next/server\";\nimport { NextResponse } from \"next/server\";\nimport { getAPISecurityHeaders, type SecurityConfig } from \"./security-headers\";\n\n/**\n * CORS configuration interface\n */\nexport interface CorsConfig {\n /** Allowed origins (default: allow configured domains only) */\n allowedOrigins?: string[];\n\n /** Allow all origins with wildcard (default: false for security) */\n allowWildcard?: boolean;\n\n /** Allow credentials to be sent (default: false) */\n allowCredentials?: boolean;\n\n /** Cache preflight requests for this many seconds (default: 86400 = 24 hours) */\n maxAge?: number;\n\n /** Security headers configuration */\n securityConfig?: SecurityConfig;\n}\n\n/**\n * Default CORS configuration for blog platform\n */\nconst DEFAULT_CORS_CONFIG: Required<CorsConfig> = {\n allowedOrigins: [\n \"http://localhost:3000\", // Development Bloggy core\n \"https://localhost:3000\", // Development Bloggy core (HTTPS)\n \"http://127.0.0.1:3000\", // Alternative localhost\n \"https://127.0.0.1:3000\", // Alternative localhost (HTTPS)\n ],\n allowWildcard: false, // Security: don't allow all origins by default\n allowCredentials: false, // Security: don't allow credentials by default\n maxAge: 86400, // Cache preflight for 24 hours\n securityConfig: {}, // Default security configuration\n};\n\n/**\n * Get CORS configuration from environment or defaults\n */\nfunction getCorsConfig(): Required<CorsConfig> {\n const envOrigins = process.env.BLOG_PLATFORM_ALLOWED_ORIGINS;\n const allowWildcard = process.env.BLOG_PLATFORM_ALLOW_WILDCARD === \"true\";\n const allowCredentials = process.env.BLOG_PLATFORM_ALLOW_CREDENTIALS === \"true\";\n \n return {\n ...DEFAULT_CORS_CONFIG,\n allowedOrigins: envOrigins ? envOrigins.split(\",\").map(origin => origin.trim()) : DEFAULT_CORS_CONFIG.allowedOrigins,\n allowWildcard,\n allowCredentials,\n };\n}\n\n/**\n * Check if an origin is allowed based on CORS configuration\n */\nfunction isOriginAllowed(origin: string | null, config: Required<CorsConfig>): boolean {\n if (!origin) {\n return false;\n }\n \n // If wildcard is enabled, allow all origins\n if (config.allowWildcard) {\n return true;\n }\n \n // Check against allowed origins list\n return config.allowedOrigins.includes(origin);\n}\n\n/**\n * Get CORS headers for a given request and configuration\n */\nfunction getCorsHeaders(request: NextRequest, config: Required<CorsConfig>): Record<string, string> {\n const origin = request.headers.get(\"origin\");\n const headers: Record<string, string> = {};\n \n // Set allowed origin\n if (config.allowWildcard) {\n headers[\"Access-Control-Allow-Origin\"] = \"*\";\n } else if (origin && isOriginAllowed(origin, config)) {\n headers[\"Access-Control-Allow-Origin\"] = origin;\n }\n \n // Set credentials if allowed (only when not using wildcard)\n if (config.allowCredentials && !config.allowWildcard) {\n headers[\"Access-Control-Allow-Credentials\"] = \"true\";\n }\n \n // Always include Vary header when not using wildcard\n if (!config.allowWildcard) {\n headers.Vary = \"Origin\";\n }\n \n return headers;\n}\n\n/**\n * Get preflight CORS headers for OPTIONS requests\n */\nfunction getPreflightHeaders(\n request: NextRequest, \n config: Required<CorsConfig>,\n allowedMethods: string[],\n allowedHeaders: string[]\n): Record<string, string> {\n const corsHeaders = getCorsHeaders(request, config);\n \n return {\n ...corsHeaders,\n \"Access-Control-Allow-Methods\": allowedMethods.join(\", \"),\n \"Access-Control-Allow-Headers\": allowedHeaders.join(\", \"),\n \"Access-Control-Max-Age\": config.maxAge.toString(),\n };\n}\n\n/**\n * Standard allowed headers for blog platform API endpoints\n */\nexport const STANDARD_ALLOWED_HEADERS = [\n \"Content-Type\",\n \"X-Bloggy-Version\", \n \"X-Idempotency-Key\",\n \"Authorization\",\n \"X-Requested-With\",\n];\n\n/**\n * Create CORS-enabled response for API endpoints\n */\nexport function createCorsResponse<T>(\n request: NextRequest,\n data: T,\n options: {\n status?: number;\n headers?: Record<string, string>;\n corsConfig?: CorsConfig;\n } = {}\n): NextResponse<T> {\n const { status = 200, headers = {}, corsConfig = {} } = options;\n const config = { ...getCorsConfig(), ...corsConfig };\n\n const corsHeaders = getCorsHeaders(request, config);\n const securityHeaders = getAPISecurityHeaders(request, config.securityConfig);\n\n const responseHeaders = {\n \"Content-Type\": \"application/json\",\n ...corsHeaders,\n ...securityHeaders,\n ...headers,\n };\n\n return NextResponse.json(data, {\n status,\n headers: responseHeaders,\n });\n}\n\n/**\n * Handle CORS preflight OPTIONS requests\n */\nexport function handleCorsOptions(\n request: NextRequest,\n allowedMethods: string[],\n options: {\n allowedHeaders?: string[];\n corsConfig?: CorsConfig;\n } = {}\n): NextResponse {\n const { allowedHeaders = STANDARD_ALLOWED_HEADERS, corsConfig = {} } = options;\n const config = { ...getCorsConfig(), ...corsConfig };\n\n const origin = request.headers.get(\"origin\");\n\n // Check if origin is allowed\n if (origin && !config.allowWildcard && !isOriginAllowed(origin, config)) {\n const securityHeaders = getAPISecurityHeaders(request, config.securityConfig);\n return new NextResponse(null, {\n status: 403,\n headers: {\n \"Content-Type\": \"text/plain\",\n ...securityHeaders,\n },\n });\n }\n\n const preflightHeaders = getPreflightHeaders(\n request,\n config,\n [...allowedMethods, \"OPTIONS\"],\n allowedHeaders\n );\n\n const securityHeaders = getAPISecurityHeaders(request, config.securityConfig);\n\n return new NextResponse(null, {\n status: 200,\n headers: {\n ...preflightHeaders,\n ...securityHeaders,\n },\n });\n}\n\n/**\n * Middleware to add CORS headers to any response\n */\nexport function addCorsHeaders(\n request: NextRequest,\n response: NextResponse,\n corsConfig: CorsConfig = {}\n): NextResponse {\n const config = { ...getCorsConfig(), ...corsConfig };\n const corsHeaders = getCorsHeaders(request, config);\n const securityHeaders = getAPISecurityHeaders(request, config.securityConfig);\n\n // Add CORS and security headers to existing response\n Object.entries({ ...corsHeaders, ...securityHeaders }).forEach(([key, value]) => {\n response.headers.set(key, value);\n });\n\n return response;\n}\n\n/**\n * Check if request origin is allowed (utility for manual CORS checking)\n */\nexport function checkOriginAllowed(request: NextRequest, corsConfig: CorsConfig = {}): boolean {\n const config = { ...getCorsConfig(), ...corsConfig };\n const origin = request.headers.get(\"origin\");\n \n return isOriginAllowed(origin, config);\n}","import type { NextRequest, NextResponse } from \"next/server\";\nimport { getStorage } from \"@/lib/database\";\nimport { getBlogPlatformVersion, parseVersionHeader } from \"@/lib/version\";\nimport { requireAuth, authenticateRequest } from \"@/lib/auth\";\nimport { enforceRateLimit, getRateLimitHeaders } from \"@/lib/ratelimit\";\nimport { createCorsResponse, handleCorsOptions } from \"@/lib/cors\";\nimport type {\n PublishPayload,\n PublishResult,\n PublishedArticle,\n} from \"@/types/contracts\";\n\n/**\n * POST /api/blog/publish\n *\n * Publishes an article to the blog platform with full idempotency support.\n * This endpoint receives content from Bloggy core and stores it for rendering.\n *\n * Request body should contain a PublishPayload with:\n * - article: The complete article data\n * - idempotencyKey: SHA-256 hash for duplicate prevention\n * - Optional overrides for slug, meta description, etc.\n */\nexport async function POST(\n request: NextRequest,\n): Promise<NextResponse<PublishResult>> {\n try {\n // Authenticate the request\n const auth = await authenticateRequest(request);\n if (!auth.authenticated) {\n const authCheck = await requireAuth(request);\n return createCorsResponse(request, authCheck.error!, { status: 401 });\n }\n\n // Apply rate limiting using the authentication token\n const token = auth.token ?? \"anonymous\";\n const rateLimitCheck = await enforceRateLimit(token);\n if (!rateLimitCheck.allowed) {\n // Extract rate limit info from error response, with safe fallback\n const rateLimitData =\n rateLimitCheck.errorResponse.error?.details?.rateLimit;\n const rateLimitResult =\n rateLimitData &&\n typeof rateLimitData === \"object\" &&\n \"limit\" in rateLimitData &&\n \"remaining\" in rateLimitData &&\n \"reset\" in rateLimitData &&\n \"count\" in rateLimitData &&\n \"success\" in rateLimitData\n ? (rateLimitData as {\n limit: number;\n remaining: number;\n reset: number;\n count: number;\n success: boolean;\n })\n : {\n limit: 10,\n remaining: 0,\n reset: Date.now() + 60000,\n count: 10,\n success: false,\n };\n\n const rateLimitHeaders = getRateLimitHeaders(rateLimitResult);\n\n return createCorsResponse(request, rateLimitCheck.errorResponse, {\n status: 429,\n headers: rateLimitHeaders,\n });\n }\n\n // Validate request content type\n const contentType = request.headers.get(\"content-type\");\n if (!contentType?.includes(\"application/json\")) {\n return createCorsResponse(\n request,\n {\n success: false,\n error: {\n code: \"PUB001\",\n message: \"Content-Type must be application/json\",\n },\n idempotencyKey: \"\",\n },\n { status: 400 },\n );\n }\n\n // Parse request body\n let payload: PublishPayload;\n try {\n payload = (await request.json()) as PublishPayload;\n } catch {\n return createCorsResponse(\n request,\n {\n success: false,\n error: {\n code: \"PUB001\",\n message: \"Invalid JSON in request body\",\n },\n idempotencyKey: \"\",\n },\n { status: 400 },\n );\n }\n\n // Validate required fields\n const validationErrors = validatePublishPayload(payload);\n if (validationErrors.length > 0) {\n return createCorsResponse(\n request,\n {\n success: false,\n error: {\n code: \"PUB001\",\n message: \"Missing required fields\",\n details: { errors: validationErrors },\n },\n idempotencyKey: payload.idempotencyKey ?? \"\",\n },\n { status: 400 },\n );\n }\n\n // Check version compatibility if header provided\n const clientVersionHeader = request.headers.get(\"X-Bloggy-Version\");\n if (clientVersionHeader) {\n const parsedVersions = parseVersionHeader(clientVersionHeader);\n if (parsedVersions?.platformVersion) {\n const platformVersion = getBlogPlatformVersion();\n\n // Check for major version incompatibility\n if (parsedVersions.platformVersion.major !== platformVersion.major) {\n return createCorsResponse(\n request,\n {\n success: false,\n error: {\n code: \"PUB009\",\n message:\n \"Major version incompatibility. Please upgrade your blog platform package.\",\n details: {\n clientVersion: parsedVersions.platformVersion.version,\n serverVersion: platformVersion.version,\n },\n },\n idempotencyKey: payload.idempotencyKey,\n },\n { status: 409 },\n );\n }\n }\n }\n\n // Handle dry run validation\n if (payload.dryRun) {\n const warnings: string[] = [];\n\n // Validate content requirements\n if (payload.article.wordCount < 50) {\n warnings.push(\"Article has fewer than 50 words, which may affect SEO\");\n }\n\n if (!payload.article.excerpt || payload.article.excerpt.length < 120) {\n warnings.push(\n \"Article excerpt is shorter than recommended 120 characters\",\n );\n }\n\n if (!payload.article.meta.keywords.length) {\n warnings.push(\"No SEO keywords provided\");\n }\n\n return createCorsResponse(\n request,\n {\n success: true,\n warnings,\n idempotencyKey: payload.idempotencyKey,\n },\n { status: 200 },\n );\n }\n\n // Prepare the article with any overrides\n const finalArticle: PublishedArticle = {\n ...payload.article,\n slug: payload.slug ?? payload.article.slug,\n meta: {\n ...payload.article.meta,\n description:\n payload.metaDescription ?? payload.article.meta.description,\n },\n };\n\n // Validate slug format\n if (!isValidSlug(finalArticle.slug)) {\n return createCorsResponse(\n request,\n {\n success: false,\n error: {\n code: \"PUB002\",\n message:\n \"Slug can only contain lowercase letters, numbers, and hyphens\",\n },\n idempotencyKey: payload.idempotencyKey,\n },\n { status: 400 },\n );\n }\n\n // Get storage and attempt to save\n const storage = getStorage();\n const result = await storage.saveArticle(\n finalArticle,\n payload.idempotencyKey,\n );\n\n // Prepare response headers\n const platformVersion = getBlogPlatformVersion();\n const rateLimitHeaders = getRateLimitHeaders(\n rateLimitCheck.rateLimitResult,\n );\n\n const responseHeaders: Record<string, string> = {\n \"X-Bloggy-Version\": `platform/${platformVersion.version}`,\n \"X-Idempotency-Key\": payload.idempotencyKey,\n ...rateLimitHeaders,\n };\n\n if (result.success) {\n responseHeaders.Location = result.url ?? `/${finalArticle.slug}`;\n }\n\n // Return appropriate status code\n const statusCode = result.success\n ? 201\n : result.error?.code === \"PUB003\"\n ? 409\n : 400;\n\n return createCorsResponse(request, result, {\n status: statusCode,\n headers: responseHeaders,\n });\n } catch (error) {\n console.error(\"Publish endpoint error:\", error);\n\n const errorResult: PublishResult = {\n success: false,\n error: {\n code: \"PUB007\",\n message: \"Internal server error during publishing\",\n },\n idempotencyKey: \"\",\n };\n\n return createCorsResponse(request, errorResult, { status: 500 });\n }\n}\n\n/**\n * OPTIONS /api/blog/publish\n *\n * Handle CORS preflight requests\n */\nexport async function OPTIONS(request: NextRequest): Promise<NextResponse> {\n return handleCorsOptions(request, [\"POST\"], {\n allowedHeaders: [\n \"Content-Type\",\n \"X-Bloggy-Version\",\n \"X-Idempotency-Key\",\n \"Authorization\",\n \"X-Requested-With\",\n ],\n });\n}\n\n/**\n * Validate the publish payload structure\n */\nfunction validatePublishPayload(payload: unknown): string[] {\n const errors: string[] = [];\n\n if (!payload || typeof payload !== \"object\") {\n errors.push(\"Request body must be a valid object\");\n return errors;\n }\n\n const p = payload as Record<string, unknown>;\n\n // Check required top-level fields\n if (!p.article || typeof p.article !== \"object\") {\n errors.push(\"Missing required field: article\");\n }\n\n if (!p.idempotencyKey || typeof p.idempotencyKey !== \"string\") {\n errors.push(\"Missing required field: idempotencyKey\");\n }\n\n // Validate article structure if present\n if (p.article && typeof p.article === \"object\") {\n const article = p.article as Record<string, unknown>;\n\n const requiredFields = [\n \"id\",\n \"slug\",\n \"title\",\n \"content\",\n \"publishedAt\",\n \"site\",\n ];\n for (const field of requiredFields) {\n if (!article[field]) {\n errors.push(`Missing required article field: ${field}`);\n }\n }\n\n // Validate site structure\n if (article.site && typeof article.site === \"object\") {\n const site = article.site as Record<string, unknown>;\n const requiredSiteFields = [\"id\", \"name\", \"domain\"];\n for (const field of requiredSiteFields) {\n if (!site[field]) {\n errors.push(`Missing required site field: ${field}`);\n }\n }\n }\n\n // Validate meta structure\n if (article.meta && typeof article.meta === \"object\") {\n const meta = article.meta as Record<string, unknown>;\n if (!Array.isArray(meta.keywords)) {\n errors.push(\"Article meta.keywords must be an array\");\n }\n }\n }\n\n return errors;\n}\n\n/**\n * Validate slug format\n * Must be lowercase, alphanumeric, and hyphens only\n */\nfunction isValidSlug(slug: string): boolean {\n if (!slug || typeof slug !== \"string\") {\n return false;\n }\n\n // Allow lowercase letters, numbers, and hyphens\n // Must start and end with alphanumeric character\n const slugRegex = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;\n return slugRegex.test(slug) && slug.length >= 1 && slug.length <= 100;\n}\n\nexport { isValidSlug };\n","import { type NextRequest, NextResponse } from \"next/server\";\nimport { getStorage } from \"@/lib/database\";\nimport { getBlogPlatformVersion, parseVersionHeader } from \"@/lib/version\";\nimport { requireAuth, authenticateRequest } from \"@/lib/auth\";\nimport { enforceRateLimit, getRateLimitHeaders } from \"@/lib/ratelimit\";\nimport { createCorsResponse, handleCorsOptions } from \"@/lib/cors\";\nimport type { UnpublishPayload, PublishResult } from \"@/types/contracts\";\n\n/**\n * POST /api/blog/unpublish\n *\n * Unpublishes an article from the blog platform with full idempotency support.\n * This endpoint receives unpublish requests from Bloggy core and removes the content.\n *\n * Request body should contain an UnpublishPayload with:\n * - slug: The article slug to unpublish\n * - idempotencyKey: SHA-256 hash for duplicate prevention\n * - Optional dry run flag for validation\n */\nexport async function POST(\n request: NextRequest,\n): Promise<NextResponse<PublishResult>> {\n try {\n // Authenticate the request\n const auth = await authenticateRequest(request);\n if (!auth.authenticated) {\n const authCheck = await requireAuth(request);\n return NextResponse.json(authCheck.error!, { status: 401 });\n }\n\n // Apply rate limiting using the authentication token\n const token = auth.token ?? \"anonymous\";\n const rateLimitCheck = await enforceRateLimit(token);\n if (!rateLimitCheck.allowed) {\n // Extract rate limit info from error response, with safe fallback\n const rateLimitData =\n rateLimitCheck.errorResponse.error?.details?.rateLimit;\n const rateLimitResult =\n rateLimitData &&\n typeof rateLimitData === \"object\" &&\n \"limit\" in rateLimitData &&\n \"remaining\" in rateLimitData &&\n \"reset\" in rateLimitData &&\n \"count\" in rateLimitData &&\n \"success\" in rateLimitData\n ? (rateLimitData as {\n limit: number;\n remaining: number;\n reset: number;\n count: number;\n success: boolean;\n })\n : {\n limit: 10,\n remaining: 0,\n reset: Date.now() + 60000,\n count: 10,\n success: false,\n };\n\n const rateLimitHeaders = getRateLimitHeaders(rateLimitResult);\n\n return createCorsResponse(request, rateLimitCheck.errorResponse, {\n status: 429,\n headers: rateLimitHeaders,\n });\n }\n\n // Validate request content type\n const contentType = request.headers.get(\"content-type\");\n if (!contentType?.includes(\"application/json\")) {\n return createCorsResponse(\n request,\n {\n success: false,\n error: {\n code: \"PUB001\",\n message: \"Content-Type must be application/json\",\n },\n idempotencyKey: \"\",\n },\n { status: 400 },\n );\n }\n\n // Parse request body\n let payload: UnpublishPayload;\n try {\n payload = (await request.json()) as UnpublishPayload;\n } catch {\n return createCorsResponse(\n request,\n {\n success: false,\n error: {\n code: \"PUB001\",\n message: \"Invalid JSON in request body\",\n },\n idempotencyKey: \"\",\n },\n { status: 400 },\n );\n }\n\n // Validate required fields\n const validationErrors = validateUnpublishPayload(payload);\n if (validationErrors.length > 0) {\n return createCorsResponse(\n request,\n {\n success: false,\n error: {\n code: \"PUB001\",\n message: \"Missing required fields\",\n details: { errors: validationErrors },\n },\n idempotencyKey: payload.idempotencyKey ?? \"\",\n },\n { status: 400 },\n );\n }\n\n // Check version compatibility if header provided\n const clientVersionHeader = request.headers.get(\"X-Bloggy-Version\");\n if (clientVersionHeader) {\n const parsedVersions = parseVersionHeader(clientVersionHeader);\n if (parsedVersions?.platformVersion) {\n const platformVersion = getBlogPlatformVersion();\n\n // Check for major version incompatibility\n if (parsedVersions.platformVersion.major !== platformVersion.major) {\n return createCorsResponse(\n request,\n {\n success: false,\n error: {\n code: \"PUB009\",\n message:\n \"Major version incompatibility. Please upgrade your blog platform package.\",\n details: {\n clientVersion: parsedVersions.platformVersion.version,\n serverVersion: platformVersion.version,\n },\n },\n idempotencyKey: payload.idempotencyKey,\n },\n { status: 409 },\n );\n }\n }\n }\n\n // Validate slug format\n if (!isValidSlug(payload.slug)) {\n return createCorsResponse(\n request,\n {\n success: false,\n error: {\n code: \"PUB002\",\n message:\n \"Slug can only contain lowercase letters, numbers, and hyphens\",\n },\n idempotencyKey: payload.idempotencyKey,\n },\n { status: 400 },\n );\n }\n\n // Handle dry run validation\n if (payload.dryRun) {\n const storage = getStorage();\n const existingArticle = await storage.getArticle(payload.slug);\n\n const warnings: string[] = [];\n if (!existingArticle) {\n warnings.push(\"Article with this slug does not exist\");\n }\n\n return createCorsResponse(\n request,\n {\n success: true,\n warnings,\n idempotencyKey: payload.idempotencyKey,\n },\n { status: 200 },\n );\n }\n\n // Get storage and attempt to remove article\n const storage = getStorage();\n const result = await storage.removeArticle(\n payload.slug,\n payload.idempotencyKey,\n );\n\n // Prepare response headers\n const platformVersion = getBlogPlatformVersion();\n const rateLimitHeaders = getRateLimitHeaders(\n rateLimitCheck.rateLimitResult,\n );\n\n const responseHeaders = {\n \"X-Bloggy-Version\": `platform/${platformVersion.version}`,\n \"X-Idempotency-Key\": payload.idempotencyKey,\n ...rateLimitHeaders,\n };\n\n // Return appropriate status code\n const statusCode = result.success\n ? 200\n : result.error?.code === \"PUB007\"\n ? 404\n : 400;\n\n return createCorsResponse(request, result, {\n status: statusCode,\n headers: responseHeaders,\n });\n } catch (error) {\n console.error(\"Unpublish endpoint error:\", error);\n\n const errorResult: PublishResult = {\n success: false,\n error: {\n code: \"PUB007\",\n message: \"Internal server error during unpublishing\",\n },\n idempotencyKey: \"\",\n };\n\n return createCorsResponse(request, errorResult, { status: 500 });\n }\n}\n\n/**\n * DELETE /api/blog/unpublish\n *\n * Alternative HTTP method for unpublishing (some clients prefer DELETE for removal operations)\n * Accepts the same payload structure as POST\n */\nexport async function DELETE(\n request: NextRequest,\n): Promise<NextResponse<PublishResult>> {\n return POST(request);\n}\n\n/**\n * OPTIONS /api/blog/unpublish\n *\n * Handle CORS preflight requests\n */\nexport async function OPTIONS(request: NextRequest): Promise<NextResponse> {\n return handleCorsOptions(request, [\"POST\", \"DELETE\"]);\n}\n\n/**\n * Validate the unpublish payload structure\n */\nfunction validateUnpublishPayload(payload: unknown): string[] {\n const errors: string[] = [];\n\n if (!payload || typeof payload !== \"object\") {\n errors.push(\"Request body must be a valid object\");\n return errors;\n }\n\n const p = payload as Record<string, unknown>;\n\n // Check required fields\n if (!p.slug || typeof p.slug !== \"string\") {\n errors.push(\"Missing required field: slug\");\n }\n\n if (!p.idempotencyKey || typeof p.idempotencyKey !== \"string\") {\n errors.push(\"Missing required field: idempotencyKey\");\n }\n\n // Validate slug is not empty\n if (p.slug && typeof p.slug === \"string\" && !p.slug.trim()) {\n errors.push(\"Slug cannot be empty\");\n }\n\n return errors;\n}\n\n/**\n * Validate slug format\n * Must be lowercase, alphanumeric, and hyphens only\n */\nfunction isValidSlug(slug: string): boolean {\n if (!slug || typeof slug !== \"string\") {\n return false;\n }\n\n // Allow lowercase letters, numbers, and hyphens\n // Must start and end with alphanumeric character\n const slugRegex = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;\n return slugRegex.test(slug) && slug.length >= 1 && slug.length <= 100;\n}\n","import type { NextRequest, NextResponse } from \"next/server\";\nimport {\n getBlogPlatformVersion,\n parseVersionHeader,\n checkVersionCompatibility,\n type VersionCompatibilityResult,\n type VersionInfo,\n} from \"@/lib/version\";\nimport { requireAuth, authenticateRequest } from \"@/lib/auth\";\nimport { enforceRateLimit, getRateLimitHeaders } from \"@/lib/ratelimit\";\nimport { createCorsResponse, handleCorsOptions } from \"@/lib/cors\";\n\n/**\n * Version compatibility response\n */\ninterface VersionResponse {\n success: boolean;\n versions: {\n bloggy: VersionInfo;\n platform: VersionInfo;\n };\n compatibility: VersionCompatibilityResult;\n error?: string;\n}\n\n/**\n * GET /api/blog/version\n *\n * Returns version information and compatibility status for Bloggy core and blog platform.\n * Used by customers to verify compatibility before publishing.\n *\n * Optional X-Bloggy-Version header can be provided to check compatibility\n * with specific versions.\n */\nexport async function GET(\n request: NextRequest,\n): Promise<NextResponse<VersionResponse>> {\n try {\n // Authenticate the request\n const auth = await authenticateRequest(request);\n if (!auth.authenticated) {\n const authCheck = await requireAuth(request);\n const errorResponse: VersionResponse = {\n success: false,\n versions: {\n bloggy: {\n name: \"unknown\",\n version: \"unknown\",\n major: 0,\n minor: 0,\n patch: 0,\n },\n platform: {\n name: \"unknown\",\n version: \"unknown\",\n major: 0,\n minor: 0,\n patch: 0,\n },\n },\n compatibility: {\n compatible: false,\n errorMessage:\n authCheck.error?.error?.message ?? \"Authentication required\",\n },\n };\n return createCorsResponse(request, errorResponse, { status: 401 });\n }\n\n // Apply rate limiting using the authentication token\n const token = auth.token ?? \"anonymous\";\n const rateLimitCheck = await enforceRateLimit(token);\n if (!rateLimitCheck.allowed) {\n // Extract rate limit info from error response, with safe fallback\n const rateLimitData =\n rateLimitCheck.errorResponse.error?.details?.rateLimit;\n const rateLimitResult =\n rateLimitData &&\n typeof rateLimitData === \"object\" &&\n \"limit\" in rateLimitData &&\n \"remaining\" in rateLimitData &&\n \"reset\" in rateLimitData &&\n \"count\" in rateLimitData &&\n \"success\" in rateLimitData\n ? (rateLimitData as {\n limit: number;\n remaining: number;\n reset: number;\n count: number;\n success: boolean;\n })\n : {\n limit: 10,\n remaining: 0,\n reset: Date.now() + 60000,\n count: 10,\n success: false,\n };\n\n const rateLimitHeaders = getRateLimitHeaders(rateLimitResult);\n\n // Create a proper version response with error\n const errorVersionResponse: VersionResponse = {\n success: false,\n versions: {\n bloggy: {\n name: \"unknown\",\n version: \"unknown\",\n major: 0,\n minor: 0,\n patch: 0,\n },\n platform: {\n name: \"unknown\",\n version: \"unknown\",\n major: 0,\n minor: 0,\n patch: 0,\n },\n },\n compatibility: {\n compatible: false,\n errorMessage:\n rateLimitCheck.errorResponse.error?.message ??\n \"Rate limit exceeded\",\n },\n };\n\n return createCorsResponse(request, errorVersionResponse, {\n status: 429,\n headers: rateLimitHeaders,\n });\n }\n\n // Get current platform version information\n const platformVersion = getBlogPlatformVersion();\n\n // Parse Bloggy version from X-Bloggy-Version header\n const clientVersionHeader = request.headers.get(\"X-Bloggy-Version\");\n let bloggyVersion: VersionInfo = {\n name: \"unknown\",\n version: \"unknown\",\n major: 0,\n minor: 0,\n patch: 0,\n };\n\n if (clientVersionHeader) {\n try {\n // Try parsing as simple version string first (e.g., \"0.1.0\")\n if (/^\\d+\\.\\d+\\.\\d+/.test(clientVersionHeader)) {\n const parts = clientVersionHeader.split(\".\");\n const major = parseInt(parts[0] ?? \"0\", 10);\n const minor = parseInt(parts[1] ?? \"0\", 10);\n const patch = parseInt(parts[2]?.split(\"-\")[0] ?? \"0\", 10);\n\n bloggyVersion = {\n name: \"bloggy\",\n version: clientVersionHeader,\n major,\n minor,\n patch,\n };\n } else {\n // Try parsing as formatted header (e.g., \"bloggy/1.0.0 platform/1.0.0\")\n const parsedVersions = parseVersionHeader(clientVersionHeader);\n if (parsedVersions?.bloggyVersion) {\n bloggyVersion = parsedVersions.bloggyVersion;\n }\n }\n } catch (error) {\n console.warn(\"Failed to parse X-Bloggy-Version header:\", error);\n }\n }\n\n // Check compatibility between Bloggy core and platform versions\n // Only perform check if we have a valid Bloggy version (not \"unknown\")\n let compatibility: VersionCompatibilityResult = { compatible: true };\n\n if (bloggyVersion.version !== \"unknown\") {\n // Compare Bloggy core version with platform version\n // Both should follow semantic versioning\n compatibility = checkVersionCompatibility(bloggyVersion, platformVersion);\n }\n\n const response: VersionResponse = {\n success: true,\n versions: {\n bloggy: bloggyVersion,\n platform: platformVersion,\n },\n compatibility,\n };\n\n // Prepare response headers\n const rateLimitHeaders = getRateLimitHeaders(\n rateLimitCheck.rateLimitResult,\n );\n\n const responseHeaders = {\n \"X-Bloggy-Version\": `platform/${platformVersion.version}`,\n \"Cache-Control\": \"public, max-age=300, stale-while-revalidate=60\",\n ...rateLimitHeaders,\n };\n\n // Always return 200 OK with compatibility details in response body\n // The client should check compatibility.compatible field, not HTTP status\n return createCorsResponse(request, response, {\n status: 200,\n headers: responseHeaders,\n });\n } catch (error) {\n console.error(\"Version endpoint error:\", error);\n\n const errorResponse: VersionResponse = {\n success: false,\n versions: {\n bloggy: {\n name: \"unknown\",\n version: \"unknown\",\n major: 0,\n minor: 0,\n patch: 0,\n },\n platform: {\n name: \"unknown\",\n version: \"unknown\",\n major: 0,\n minor: 0,\n patch: 0,\n },\n },\n compatibility: {\n compatible: false,\n errorMessage:\n \"Internal server error while checking version compatibility\",\n },\n error: error instanceof Error ? error.message : \"Unknown error\",\n };\n\n return createCorsResponse(request, errorResponse, { status: 500 });\n }\n}\n\n/**\n * OPTIONS /api/blog/version\n *\n * Handle CORS preflight requests\n */\nexport async function OPTIONS(request: NextRequest): Promise<NextResponse> {\n return handleCorsOptions(request, [\"GET\"], {\n allowedHeaders: [\n \"Content-Type\",\n \"X-Bloggy-Version\",\n \"Authorization\",\n \"X-Requested-With\",\n ],\n });\n}\n","import { type NextRequest, NextResponse } from \"next/server\";\nimport { getStorage } from \"@/lib/database\";\nimport { getBlogPlatformVersion, parseVersionHeader } from \"@/lib/version\";\nimport { requireAuth, authenticateRequest } from \"@/lib/auth\";\nimport { enforceRateLimit, getRateLimitHeaders } from \"@/lib/ratelimit\";\nimport { createCorsResponse, handleCorsOptions } from \"@/lib/cors\";\nimport { isValidSlug } from \"@/app/api/blog/publish/route\"; // Reuse slug validation from publish\n\n/**\n * GET /api/blog/slugs/{slug}\n *\n * Checks if a slug is already in use on the blog platform.\n * Used for dry-run validation in publishing workflow.\n *\n * Returns: { exists: boolean, message?: string }\n * - exists: false -> available\n * - exists: true -> taken, with suggestion message\n */\nexport async function GET(\n request: NextRequest,\n { params }: { params: Promise<{ slug: string }> },\n): Promise<NextResponse> {\n try {\n const { slug } = await params;\n // Authenticate (required for security)\n const auth = await authenticateRequest(request);\n if (!auth.authenticated) {\n const authCheck = await requireAuth(request);\n return NextResponse.json(authCheck.error!, { status: 401 });\n }\n\n const token = auth.token ?? \"anonymous\";\n\n // Rate limiting (same as publish: 5/min per token)\n const rateLimitCheck = await enforceRateLimit(token);\n if (!rateLimitCheck.allowed) {\n const rateLimitData = (rateLimitCheck.errorResponse.error?.details\n ?.rateLimit as {\n limit: number;\n remaining: number;\n reset: number;\n count: number;\n success: boolean;\n }) || {\n limit: 10,\n remaining: 0,\n reset: Date.now() + 60000,\n count: 10,\n success: false,\n };\n\n const rateLimitHeaders = getRateLimitHeaders(rateLimitData);\n\n return createCorsResponse(request, rateLimitCheck.errorResponse, {\n status: 429,\n headers: rateLimitHeaders,\n });\n }\n\n // Extract slug from params\n if (!slug || !isValidSlug(slug)) {\n return createCorsResponse(\n request,\n {\n exists: false, // Treat invalid as non-existent, but error for clarity\n error: {\n code: \"PUB002\",\n message:\n \"Invalid slug format. Must be lowercase letters, numbers, and hyphens only.\",\n },\n },\n { status: 400 },\n );\n }\n\n // Version compatibility check\n const clientVersionHeader = request.headers.get(\"X-Bloggy-Version\");\n if (clientVersionHeader) {\n const parsedVersions = parseVersionHeader(clientVersionHeader);\n if (parsedVersions?.platformVersion) {\n const platformVersion = getBlogPlatformVersion();\n if (parsedVersions.platformVersion.major !== platformVersion.major) {\n return createCorsResponse(\n request,\n {\n exists: false,\n error: {\n code: \"PUB009\",\n message:\n \"Major version incompatibility. Please upgrade your blog platform package.\",\n details: {\n clientVersion: parsedVersions.platformVersion.version,\n serverVersion: platformVersion.version,\n },\n },\n },\n { status: 409 },\n );\n }\n }\n }\n\n // Check existence via storage\n const storage = getStorage();\n const existingArticle = await storage.getArticle(slug);\n const exists = existingArticle !== null;\n\n const responseBody = {\n exists,\n ...(exists && {\n message:\n \"Slug is already in use. Please choose another (e.g., append '-v2').\",\n }),\n };\n\n // Headers\n const platformVersion = getBlogPlatformVersion();\n const rateLimitHeaders = getRateLimitHeaders(\n rateLimitCheck.rateLimitResult,\n );\n const responseHeaders: Record<string, string> = {\n \"X-Bloggy-Version\": `platform/${platformVersion.version}`,\n ...rateLimitHeaders,\n };\n\n // Optional idempotency log (if provided)\n const idempotencyKey = request.headers.get(\"X-Idempotency-Key\");\n if (idempotencyKey) {\n responseHeaders[\"X-Idempotency-Key\"] = idempotencyKey;\n // Log for debugging\n console.log(\n `Slug check for idempotency: ${idempotencyKey}, exists: ${exists}`,\n );\n }\n\n return createCorsResponse(request, responseBody, {\n status: 200,\n headers: responseHeaders,\n });\n } catch (error: unknown) {\n console.error(\n \"Slug existence check error:\",\n error instanceof Error ? error.message : String(error),\n );\n\n return createCorsResponse(\n request,\n {\n exists: false,\n error: {\n code: \"PUB007\",\n message: \"Internal server error during slug check\",\n },\n },\n { status: 500 },\n );\n }\n}\n\n/**\n * OPTIONS /api/blog/slugs/{slug}\n * Handle CORS preflight\n */\nexport async function OPTIONS(request: NextRequest): Promise<NextResponse> {\n return handleCorsOptions(request, [\"GET\"]);\n}\n","/**\n * @xexr/blog-platform\n *\n * SEO-friendly blog platform for Next.js with Bloggy integration.\n * Enables publishing AI-generated content to custom domains.\n */\n\n// Re-export all public types\nexport * from \"./types\";\n\n// Component exports\nexport {\n default as BlogHomePage,\n generateBlogHomeMetadata,\n} from \"./app/blog/page\";\nexport {\n default as BlogArticlePage,\n generateArticleMetadata,\n} from \"./app/blog/[slug]/page\";\nexport {\n default as BlogAuthorPage,\n generateAuthorPageMetadata,\n} from \"./app/blog/authors/[slug]/page\";\nexport {\n default as Pagination,\n usePagination,\n generatePaginationMetadata,\n} from \"./components/Pagination\";\n\n// UI Component exports\nexport { Button, buttonVariants } from \"./components/ui/button\";\nexport {\n Card,\n CardHeader,\n CardTitle,\n CardDescription,\n CardContent,\n CardFooter,\n} from \"./components/ui/card\";\nexport {\n Pagination as ShadcnPagination,\n PaginationContent,\n PaginationItem,\n PaginationLink,\n PaginationNext,\n PaginationPrevious,\n PaginationEllipsis,\n} from \"./components/ui/pagination\";\n\n// Utility exports\nexport { cn } from \"./lib/utils\";\nexport {\n normalizeBlogBasePath,\n buildAuthorPath,\n buildBlogPath,\n getPathPrefixFromBlogUrl,\n} from \"./lib/urls\";\nexport {\n type AuthorArchive,\n type AuthorArchiveOptions,\n getAuthorArchive,\n getAuthorsFromArticles,\n loadAuthorArchive,\n} from \"./lib/authors\";\nexport {\n type BlogTheme,\n extractTableOfContents,\n formatArticleDateMeta,\n getBlogThemeStyle,\n} from \"./lib/article-ui\";\nexport {\n type TopicArchive,\n getAllTopics,\n getArticlePrimaryTopic,\n getTopicArchive,\n} from \"./lib/topics\";\nexport {\n BlogTopicArchivePage,\n BlogTopicsIndexPage,\n} from \"./components/TopicArchivePages\";\nexport { BlogAuthorsIndexPage } from \"./components/AuthorPages\";\nexport {\n NewsletterSignup,\n NEWSLETTER_SUCCESS_MESSAGE,\n type NewsletterSignupProps,\n} from \"./components/NewsletterSignup\";\n\n// Initialization exports\nexport {\n initBlogPlatform,\n initBlogPlatformDev,\n initBlogPlatformProd,\n initBlogPlatformOnce,\n type BlogPlatformConfig,\n} from \"./lib/init\";\n\n// Authentication exports\nexport {\n type AuthConfig,\n type AuthResult,\n ApiKeyAuth,\n EnvAuth,\n NoAuth,\n UninitializedAuth,\n extractTokenFromHeader,\n setAuthConfig,\n getAuthConfig,\n initEnvAuth,\n shouldSkipAuth,\n} from \"./lib/auth\";\n\n// Database exports\nexport {\n type BlogPlatformStorage,\n InMemoryStorage,\n getStorage,\n setStorage,\n} from \"./lib/database\";\n\n// Drizzle storage adapter exports\nexport {\n DrizzleStorage,\n bpArticles,\n bpOperations,\n getDrizzleAdapterSql,\n} from \"./lib/storage/drizzle\";\n\n// Rate limiting exports\nexport {\n type RateLimitConfig,\n type RateLimitResult,\n configureRateLimit,\n autoConfigureRateLimit,\n checkRateLimit,\n enforceRateLimit,\n getRateLimitHeaders,\n createRateLimitErrorResponse,\n} from \"./lib/ratelimit\";\n\n// SEO utility exports\nexport {\n type CanonicalUrlOptions,\n normalizeDomain,\n normalizeSlug,\n generateCanonicalUrl,\n generateCanonicalUrlFromSlug,\n isValidCanonicalUrl,\n getBaseUrl,\n updateArticleCanonicalUrl,\n} from \"./lib/seo\";\n\n// Metadata utility exports\nexport {\n type MetadataOptions,\n type GeneratedMetadata,\n type MetaTag,\n type LinkTag,\n generateSiteMetadata,\n metadataToHtml,\n validateMetadata,\n} from \"./lib/metadata\";\n\n// Sitemap utility exports\nexport {\n type SitemapOptions,\n type SitemapChangeFreq,\n type NextjsSitemapEntry,\n type BlogSitemapConfig,\n generateBlogSitemapEntries,\n createBlogSitemapRoute,\n createDynamicBlogSitemap,\n // Legacy exports (deprecated)\n type SitemapEntry,\n type SitemapData,\n generateSitemap,\n sitemapToXml,\n generateSitemapIndex,\n validateSitemap,\n} from \"./lib/sitemap\";\n\n// Structured data utility exports\nexport {\n type PersonSchema,\n type OrganizationSchema,\n type BlogPostingSchema,\n type WebSiteSchema,\n type BreadcrumbListSchema,\n type StructuredDataOptions,\n generateArticleStructuredData,\n generateAuthorStructuredData,\n generateOrganizationStructuredData,\n generateWebSiteStructuredData,\n generateBreadcrumbStructuredData,\n generateCompleteArticleStructuredData,\n generateBlogHomeStructuredData,\n validateStructuredData,\n structuredDataToJsonLd,\n createStructuredDataScript,\n extractKeywordsFromArticle,\n safeGenerateArticleStructuredData,\n StructuredDataError,\n} from \"./lib/structured-data\";\n\n// API Route handlers\nexport { POST as publishHandler } from \"./app/api/blog/publish/route\";\nexport { POST as unpublishHandler } from \"./app/api/blog/unpublish/route\";\nexport { GET as versionHandler } from \"./app/api/blog/version/route\";\nexport {\n GET as slugExistsHandler,\n OPTIONS as slugExistsOptionsHandler,\n} from \"./app/api/blog/slugs/[slug]/route\";\n\n// Version information\n// Export package version (imported from package.json at build time)\nimport packageJson from \"../package.json\";\nexport const PACKAGE_VERSION = packageJson.version;\n"]}
1
+ {"version":3,"sources":["../src/lib/utils.ts","../src/components/ui/button.tsx","../src/components/ui/pagination.tsx","../src/components/Pagination.tsx","../src/lib/urls.ts","../src/lib/structured-data.ts","../src/lib/article-ui.ts","../src/components/NewsletterSignup.tsx","../src/app/blog/page.tsx","../src/components/ui/badge.tsx","../src/components/ui/card.tsx","../src/components/ArticleTopActions.tsx","../src/components/ExpandableArticleImage.tsx","../src/components/ArticleReadingProgress.tsx","../src/components/ui/separator.tsx","../src/lib/mdx.ts","../src/app/blog/%5Bslug%5D/page.tsx","../src/app/blog/authors/%5Bslug%5D/page.tsx","../src/lib/database.ts","../src/lib/authors.ts","../src/lib/topics.ts","../src/components/TopicArchivePages.tsx","../src/components/AuthorPages.tsx","../src/lib/auth.ts","../src/lib/ratelimit.ts","../src/lib/init.ts","../src/lib/storage/drizzle.ts","../src/lib/seo.ts","../src/lib/metadata.ts","../src/lib/sitemap.ts","../package.json","../src/lib/version.ts","../src/lib/security-headers.ts","../src/lib/cors.ts","../src/app/api/blog/publish/route.ts","../src/app/api/blog/unpublish/route.ts","../src/app/api/blog/version/route.ts","../src/app/api/blog/slugs/%5Bslug%5D/route.ts","../src/index.ts"],"names":["cn","inputs","twMerge","clsx","buttonVariants","cva","Button","className","variant","size","asChild","props","jsx","Slot","Pagination","PaginationContent","PaginationItem","PaginationLink","isActive","PaginationPrevious","jsxs","ChevronLeftIcon","PaginationNext","ChevronRightIcon","PaginationEllipsis","MoreHorizontalIcon","currentPage","totalPages","baseUrl","maxVisiblePages","showPrevNext","showFirstLast","getVisiblePages","half","start","end","pages","_","i","getPageUrl","page","hasPrevious","hasNext","Fragment","ChevronsLeft","ChevronsRight","usePagination","searchParams","itemsPerPage","pageParam","pageString","offset","totalItems","generatePaginationMetadata","siteUrl","canonicalUrl","prevUrl","nextUrl","normalizeBlogBasePath","basePath","trimmed","buildBlogPath","slug","normalizedBasePath","cleanSlug","buildAuthorPath","authorSlug","getPathPrefixFromBlogUrl","blogUrl","parsed","generateArticleStructuredData","article","options","customDomain","pathPrefix","language","isAccessibleForFree","includeOptionalProperties","domain","authorSchema","generateAuthorStructuredData","publisherSchema","generateOrganizationStructuredData","timeRequired","schema","topic","author","sameAs","url","authorUrl","site","generateWebSiteStructuredData","includeSearchAction","generateBreadcrumbStructuredData","breadcrumbs","crumb","index","generateCompleteArticleStructuredData","schemas","generateBlogHomeStructuredData","featuredArticles","articleSchemas","validateStructuredData","errors","blogSchema","structuredDataToJsonLd","createStructuredDataScript","extractKeywordsFromArticle","keywords","keyword","tone","StructuredDataError","message","code","details","safeGenerateArticleStructuredData","validation","error","BLOG_PAGE_TITLE_GRADIENT_CLASS","DEFAULT_THEME","getBlogThemeStyle","theme","formatArticleDateMeta","publishedAt","updatedAt","publishedDate","updatedDate","format","formatDistanceToNow","extractTableOfContents","markdown","items","inFence","line","match","text","stripMarkdownInline","slugifyHeading","formatTableOfContentsSummary","count","getTocItemState","itemId","activeItemId","value","NEWSLETTER_SUCCESS_MESSAGE","NewsletterSignup","siteId","settings","sourceSurface","sourceArticleSlug","sourceUrl","previewMode","setMessage","useState","setError","hasSubmitted","setHasSubmitted","isSubmitting","setIsSubmitting","subscriptionKey","getSubscriptionStorageKey","hasStoredSubscribed","useSyncExternalStore","subscribeToStoredSubscription","hasStoredSubscription","hasSubscribed","handleSubmit","event","formData","honeypot","getFormString","response","getOptionalFormString","resolveSourceUrl","result","successMessage","getNewsletterResponseMessage","storeSubscription","Check","ArrowUpRight","key","cookie","callback","BlogHomePage","articles","siteName","siteTagline","includeStructuredData","pagination","newsletter","newsletterPreviewMode","newsletterSettings","newsletterSiteId","Link","ArticlePreview","structuredDataProps","formatReadingTime","seconds","articleUrl","formattedDate","readingTime","imageUrl","Image","AuthorLink","TopicChip","AuthorAvatar","sizeClass","initials","getAuthorInitials","name","part","generateBlogHomeMetadata","siteDescription","baseTitle","title","description","badgeVariants","Badge","Card","CardHeader","CardTitle","CardDescription","CardContent","CardFooter","resolveShareUrl","currentHref","copyArticleLink","clipboard","fallbackDocument","textarea","shareArticle","navigatorLike","ArticleTopActions","copied","setCopied","React","sharing","setSharing","resolvedUrl","timeout","handleCopy","handleShare","buttonClassName","iconClassName","Copy","Share2","ExpandableArticleImage","alt","src","previewId","hashImageSrc","hash","ArticleReadingProgress","contentId","showProgress","itemIds","useMemo","item","ArticleReadingProgressController","ArticleTableOfContents","useEffect","animationFrameId","pendingHashItemId","setActiveItem","tocLinks","link","updateScrollState","contentElement","progressElements","contentRect","scrollTop","contentTop","readableDistance","nextProgress","progress","normalizeProgress","progressElement","headings","id","heading","activeOffset","activeHeading","scheduleUpdate","handleHashChange","list","itemState","Separator","Dt","orientation","decorative","ref","articleMdxOptions","remarkToc","remarkGfm","rehypeUnwrapStandaloneImages","rehypeSlug","tree","unwrapStandaloneImages","node","child","isStandaloneImageParagraph","isMeaningfulNode","meaningfulChildren","isImageLikeNode","formatCreditUrl","FeaturedImageCredit","creditText","creditUrl","label","ArticlePage","navigation","postArticleCta","relatedArticles","showShareLinks","dateMeta","tocItems","hasFeaturedImageMeta","ArrowLeft","MDXRemote","AuthorSocialLinks","PostArticleCta","ArticleShareLinks","RelatedArticles","ArticleCardImage","links","getAuthorSocialLinks","Globe","FaXTwitter","FaLinkedinIn","FaGithub","Mail","cta","encodedTitle","encodedUrl","generateArticleMetadata","ogImage","AuthorPage","backUrl","totalArticleCount","AuthorArticlePreview","publishedRelativeLabel","generateAuthorPageMetadata","InMemoryStorage","idempotencyKey","existingResult","limit","sortBy","order","allArticles","a","b","aValue","bValue","warnAboutEphemeralStorage","globalRef","getGlobalStorage","storage","getStorage","setStorage","getAuthorsFromArticles","authorsBySlug","mergeAuthorProfile","getAuthorArchive","authorArticles","preferredAuthor","loadAuthorArchive","current","next","getArticlePrimaryTopic","topics","getAllTopics","topicsBySlug","getTopicArchive","topicSlug","matchingArticles","candidate","BlogTopicsIndexPage","articleTopic","BlogTopicArchivePage","archive","TopicArticleCard","publishedAgo","BlogAuthorsIndexPage","authors","createTokenFingerprint","token","createHash","extractTokenFromHeader","request","authHeader","bearerMatch","tokenMatch","ApiKeyAuth","apiKeys","EnvAuth","envVarName","apiKeysEnv","NoAuth","UninitializedAuth","_token","getDefaultAuthConfig","setAuthConfig","config","getAuthConfig","initEnvAuth","authenticateRequest","createAuthErrorResponse","authResult","customMessages","requireAuth","auth","shouldSkipAuth","skipAuth","getRateLimiter","setRateLimiter","instance","configureRateLimit","redisUrl","redisToken","requestsPerMinute","keyPrefix","analytics","redis","Redis","limiter","Ratelimit","autoConfigureRateLimit","checkRateLimit","identifier","createRateLimitErrorResponse","rateLimitResult","resetMinutes","enforceRateLimit","getRateLimitHeaders","initBlogPlatform","rateLimit","autoRateLimit","initBlogPlatformOnce","initBlogPlatformDev","initBlogPlatformProd","apiKeysEnvVar","envVar","bpArticles","sqliteTable","integer","table","uniqueIndex","bpOperations","toRow","fromRow","row","extractTopics","extractMeta","metaJson","DrizzleStorage","db","existing","eq","bySlug","existingRow","conflict","and","success","rows","orderColumn","orderBy","desc","totalRow","sql","total","notFound","now","expiresAt","getDrizzleAdapterSql","normalizeDomain","forceHttps","normalized","normalizeSlug","clean","generateCanonicalUrl","removeTrailingSlash","normalizedDomain","normalizedSlug","cleanPrefix","generateCanonicalUrlFromSlug","isValidCanonicalUrl","getBaseUrl","updateArticleCanonicalUrl","generateSiteMetadata","pageInfo","path","meta","openGraph","twitter","generateTwitterCardMetadata","overrides","image","metadataToHtml","metadata","elements","escapeHtml","tag","attrs","htmlEscapes","char","validateMetadata","warnings","generateBlogSitemapEntries","includeAuthorPages","includeTopicPages","includePaginationPages","articlesPerPage","maxEntries","changeFrequency","priority","entries","sitemapAuthors","sitemapTopics","getLatestModificationDate","topicArticles","latestAuthorMod","generateSitemap","generatedAt","potentialEntries","willTruncate","sitemapToXml","sitemapData","xmlHeader","urlsetOpen","urlsetClose","urlEntries","entry","escapeXml","generateSitemapIndex","sitemaps","_baseUrl","indexOpen","indexClose","sitemapEntries","sitemap","validateSitemap","isValidISODate","urlCounts","latest","articleDate","createBlogSitemapRoute","xmlEntries","xml","createDynamicBlogSitemap","staticRoutes","xmlEscapes","dateString","date","isoString","normalizedInput","package_default","parseVersion","version","parts","major","minor","patch","getBlogPlatformVersion","versionComponents","parseVersionHeader","headerValue","versionInfo","checkVersionCompatibility","version1","version2","DEFAULT_SECURITY_CONFIG","getSecurityConfig","envCSPDisabled","envFrameOptions","envHSTSDisabled","buildCSPHeader","directives","directive","buildPermissionsPolicyHeader","feature","allowlist","getSecurityHeaders","securityConfig","headers","cspDirectives","isHTTPS","hstsValue","permissionsDirectives","getAPISecurityHeaders","DEFAULT_CORS_CONFIG","getCorsConfig","envOrigins","allowWildcard","allowCredentials","origin","isOriginAllowed","getCorsHeaders","getPreflightHeaders","allowedMethods","allowedHeaders","STANDARD_ALLOWED_HEADERS","createCorsResponse","data","status","corsConfig","corsHeaders","securityHeaders","responseHeaders","NextResponse","handleCorsOptions","preflightHeaders","POST","authCheck","tokenFingerprint","rateLimitCheck","rateLimitData","rateLimitHeaders","payload","validationErrors","validatePublishPayload","clientVersionHeader","parsedVersions","platformVersion","finalArticle","isValidSlug","statusCode","p","requiredFields","field","requiredSiteFields","validateUnpublishPayload","existingArticle","GET","errorResponse","errorVersionResponse","bloggyVersion","compatibility","params","exists","responseBody","OPTIONS","PACKAGE_VERSION"],"mappings":"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","file":"index.mjs","sourcesContent":["import { clsx, type ClassValue } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n","import * as React from \"react\"\nimport { Slot } from \"@radix-ui/react-slot\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"../../lib/utils\"\n\nconst buttonVariants = cva(\n \"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive\",\n {\n variants: {\n variant: {\n default:\n \"bg-primary text-primary-foreground shadow-xs hover:bg-primary/90\",\n destructive:\n \"bg-destructive text-white shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60\",\n outline:\n \"border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50\",\n secondary:\n \"bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80\",\n ghost:\n \"hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50\",\n link: \"text-primary underline-offset-4 hover:underline\",\n },\n size: {\n default: \"h-9 px-4 py-2 has-[>svg]:px-3\",\n sm: \"h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5\",\n lg: \"h-10 rounded-md px-6 has-[>svg]:px-4\",\n icon: \"size-9\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n }\n)\n\nfunction Button({\n className,\n variant,\n size,\n asChild = false,\n ...props\n}: React.ComponentProps<\"button\"> &\n VariantProps<typeof buttonVariants> & {\n asChild?: boolean\n }) {\n const Comp = asChild ? Slot : \"button\"\n\n return (\n <Comp\n data-slot=\"button\"\n className={cn(buttonVariants({ variant, size, className }))}\n {...props}\n />\n )\n}\n\nexport { Button, buttonVariants }\n","import * as React from \"react\"\nimport {\n ChevronLeftIcon,\n ChevronRightIcon,\n MoreHorizontalIcon,\n} from \"lucide-react\"\n\nimport { cn } from \"../../lib/utils\"\nimport { buttonVariants } from \"./button\"\n\nfunction Pagination({ className, ...props }: React.ComponentProps<\"nav\">) {\n return (\n <nav\n role=\"navigation\"\n aria-label=\"pagination\"\n data-slot=\"pagination\"\n className={cn(\"mx-auto flex w-full justify-center\", className)}\n {...props}\n />\n )\n}\n\nfunction PaginationContent({\n className,\n ...props\n}: React.ComponentProps<\"ul\">) {\n return (\n <ul\n data-slot=\"pagination-content\"\n className={cn(\"flex flex-row items-center gap-1\", className)}\n {...props}\n />\n )\n}\n\nfunction PaginationItem({ ...props }: React.ComponentProps<\"li\">) {\n return <li data-slot=\"pagination-item\" {...props} />\n}\n\ntype PaginationLinkProps = {\n isActive?: boolean\n size?: \"default\" | \"sm\" | \"lg\" | \"icon\"\n} & React.ComponentProps<\"a\">\n\nfunction PaginationLink({\n className,\n isActive,\n size = \"icon\",\n ...props\n}: PaginationLinkProps) {\n return (\n <a\n aria-current={isActive ? \"page\" : undefined}\n data-slot=\"pagination-link\"\n data-active={isActive}\n className={cn(\n buttonVariants({\n variant: isActive ? \"outline\" : \"ghost\",\n size,\n }),\n className\n )}\n {...props}\n />\n )\n}\n\nfunction PaginationPrevious({\n className,\n ...props\n}: React.ComponentProps<typeof PaginationLink>) {\n return (\n <PaginationLink\n aria-label=\"Go to previous page\"\n size=\"default\"\n className={cn(\"gap-1 px-2.5 sm:pl-2.5\", className)}\n {...props}\n >\n <ChevronLeftIcon />\n <span className=\"hidden sm:block\">Previous</span>\n </PaginationLink>\n )\n}\n\nfunction PaginationNext({\n className,\n ...props\n}: React.ComponentProps<typeof PaginationLink>) {\n return (\n <PaginationLink\n aria-label=\"Go to next page\"\n size=\"default\"\n className={cn(\"gap-1 px-2.5 sm:pr-2.5\", className)}\n {...props}\n >\n <span className=\"hidden sm:block\">Next</span>\n <ChevronRightIcon />\n </PaginationLink>\n )\n}\n\nfunction PaginationEllipsis({\n className,\n ...props\n}: React.ComponentProps<\"span\">) {\n return (\n <span\n aria-hidden\n data-slot=\"pagination-ellipsis\"\n className={cn(\"flex size-9 items-center justify-center\", className)}\n {...props}\n >\n <MoreHorizontalIcon className=\"size-4\" />\n <span className=\"sr-only\">More pages</span>\n </span>\n )\n}\n\nexport {\n Pagination,\n PaginationContent,\n PaginationLink,\n PaginationItem,\n PaginationPrevious,\n PaginationNext,\n PaginationEllipsis,\n}\n","import React from \"react\";\nimport { ChevronsLeft, ChevronsRight } from \"lucide-react\";\nimport {\n Pagination as ShadcnPagination,\n PaginationContent,\n PaginationItem,\n PaginationLink,\n PaginationNext,\n PaginationPrevious,\n PaginationEllipsis,\n} from \"./ui/pagination\";\n\nexport interface PaginationProps {\n /** Current page number (1-indexed) */\n currentPage: number;\n \n /** Total number of pages */\n totalPages: number;\n \n /** Base URL for pagination links (e.g., \"/blog\") */\n baseUrl: string;\n \n /** Additional CSS classes */\n className?: string;\n \n /** Maximum number of page links to show around current page */\n maxVisiblePages?: number;\n \n /** Show/hide previous and next buttons */\n showPrevNext?: boolean;\n \n /** Show/hide first and last page links */\n showFirstLast?: boolean;\n \n /** Custom labels for navigation */\n labels?: {\n previous?: string;\n next?: string;\n first?: string;\n last?: string;\n };\n}\n\n/**\n * Pagination component for blog articles listing.\n * \n * Provides SEO-friendly pagination with proper URL structure,\n * keyboard navigation, and accessibility features.\n */\nexport default function Pagination({\n currentPage,\n totalPages,\n baseUrl,\n className,\n maxVisiblePages = 5,\n showPrevNext = true,\n showFirstLast = true,\n}: PaginationProps) {\n // Don't render pagination if there's only one page or no pages\n if (totalPages <= 1) {\n return null;\n }\n\n // Calculate visible page range\n const getVisiblePages = () => {\n const half = Math.floor(maxVisiblePages / 2);\n let start = Math.max(1, currentPage - half);\n const end = Math.min(totalPages, start + maxVisiblePages - 1);\n \n // Adjust start if we're near the end\n if (end - start + 1 < maxVisiblePages) {\n start = Math.max(1, end - maxVisiblePages + 1);\n }\n \n return { start, end };\n };\n\n const { start, end } = getVisiblePages();\n const pages = Array.from({ length: end - start + 1 }, (_, i) => start + i);\n\n // Generate URL for a specific page\n const getPageUrl = (page: number) => {\n if (page === 1) {\n return baseUrl;\n }\n return `${baseUrl}?page=${page}`;\n };\n\n const hasPrevious = currentPage > 1;\n const hasNext = currentPage < totalPages;\n\n return (\n <ShadcnPagination className={className}>\n <PaginationContent>\n {/* First Page Link */}\n {showFirstLast && currentPage > 2 && (\n <>\n <PaginationItem>\n <PaginationLink href={getPageUrl(1)} aria-label=\"Go to first page\">\n <ChevronsLeft className=\"h-4 w-4\" />\n </PaginationLink>\n </PaginationItem>\n {start > 2 && (\n <PaginationItem>\n <PaginationEllipsis />\n </PaginationItem>\n )}\n </>\n )}\n\n {/* Previous Page Link */}\n {showPrevNext && (\n <PaginationItem>\n {hasPrevious ? (\n <PaginationPrevious href={getPageUrl(currentPage - 1)} />\n ) : (\n <span className=\"flex h-9 items-center justify-center gap-1 px-2.5 text-muted-foreground sm:pl-2.5\">\n <span className=\"hidden sm:block\">Previous</span>\n </span>\n )}\n </PaginationItem>\n )}\n\n {/* Page Number Links */}\n {pages.map((page) => (\n <PaginationItem key={page}>\n <PaginationLink \n href={getPageUrl(page)}\n isActive={page === currentPage}\n >\n {page}\n </PaginationLink>\n </PaginationItem>\n ))}\n\n {/* Next Page Link */}\n {showPrevNext && (\n <PaginationItem>\n {hasNext ? (\n <PaginationNext href={getPageUrl(currentPage + 1)} />\n ) : (\n <span className=\"flex h-9 items-center justify-center gap-1 px-2.5 text-muted-foreground sm:pr-2.5\">\n <span className=\"hidden sm:block\">Next</span>\n </span>\n )}\n </PaginationItem>\n )}\n\n {/* Last Page Link */}\n {showFirstLast && currentPage < totalPages - 1 && (\n <>\n {end < totalPages - 1 && (\n <PaginationItem>\n <PaginationEllipsis />\n </PaginationItem>\n )}\n <PaginationItem>\n <PaginationLink href={getPageUrl(totalPages)} aria-label=\"Go to last page\">\n <ChevronsRight className=\"h-4 w-4\" />\n </PaginationLink>\n </PaginationItem>\n </>\n )}\n </PaginationContent>\n\n {/* Screen Reader Info */}\n <div className=\"sr-only\" aria-live=\"polite\">\n Page {currentPage} of {totalPages}\n </div>\n </ShadcnPagination>\n );\n}\n\n\n/**\n * Hook to calculate pagination metadata from URL parameters.\n * Useful for extracting current page from Next.js searchParams.\n */\nexport function usePagination(\n searchParams: Record<string, string | string[] | undefined>,\n itemsPerPage = 10\n) {\n const pageParam = searchParams.page;\n const pageString = Array.isArray(pageParam) ? pageParam[0] : pageParam;\n const currentPage = Math.max(1, parseInt(pageString ?? \"1\", 10));\n\n const offset = (currentPage - 1) * itemsPerPage;\n\n const calculateTotalPages = (totalItems: number) => {\n return Math.ceil(totalItems / itemsPerPage);\n };\n\n return {\n currentPage,\n itemsPerPage,\n offset,\n calculateTotalPages\n };\n}\n\n/**\n * Generate pagination metadata for SEO.\n * Provides canonical URLs, next/prev relationships for search engines.\n */\nexport function generatePaginationMetadata(\n currentPage: number,\n totalPages: number,\n baseUrl: string,\n siteUrl?: string\n) {\n const canonicalUrl = siteUrl \n ? `${siteUrl}${currentPage === 1 ? baseUrl : `${baseUrl}?page=${currentPage}`}`\n : undefined;\n\n const prevUrl = currentPage > 1 \n ? siteUrl \n ? `${siteUrl}${currentPage === 2 ? baseUrl : `${baseUrl}?page=${currentPage - 1}`}`\n : undefined\n : undefined;\n\n const nextUrl = currentPage < totalPages \n ? siteUrl \n ? `${siteUrl}${baseUrl}?page=${currentPage + 1}`\n : undefined\n : undefined;\n\n return {\n alternates: {\n ...(canonicalUrl && { canonical: canonicalUrl }),\n },\n other: {\n ...(prevUrl && { prev: prevUrl }),\n ...(nextUrl && { next: nextUrl }),\n },\n };\n}","/**\n * URL helpers shared by package UI, metadata, and sitemap integrations.\n */\n\nexport function normalizeBlogBasePath(basePath = \"/blog\"): string {\n const trimmed = basePath.trim();\n if (!trimmed || trimmed === \"/\") return \"\";\n\n return trimmed.replace(/^(?!\\/)/, \"/\").replace(/\\/+$/, \"\");\n}\n\nexport function buildBlogPath(\n basePath: string | undefined,\n slug?: string,\n): string {\n const normalizedBasePath = normalizeBlogBasePath(basePath);\n const cleanSlug = slug?.replace(/^\\/+/, \"\").replace(/\\/+$/, \"\");\n\n if (!cleanSlug) {\n return normalizedBasePath || \"/\";\n }\n\n return `${normalizedBasePath}/${cleanSlug}`.replace(/\\/+/g, \"/\");\n}\n\nexport function buildAuthorPath(\n basePath: string | undefined,\n authorSlug: string,\n): string {\n return buildBlogPath(basePath, `authors/${authorSlug}`);\n}\n\nexport function getPathPrefixFromBlogUrl(blogUrl: string): string {\n const parsed = new URL(blogUrl);\n return normalizeBlogBasePath(parsed.pathname);\n}\n","/**\n * Structured Data (JSON-LD) utilities for SEO optimization\n *\n * This module provides comprehensive schema.org structured data generation\n * for blog articles, authors, and organizations. It follows Google's\n * recommended guidelines for structured data markup.\n *\n * @see https://developers.google.com/search/docs/appearance/structured-data\n * @see https://schema.org/\n */\n\nimport type {\n PublishedArticle,\n PublishedAuthor,\n PublishedSite,\n} from \"../types/contracts\";\nimport { buildAuthorPath } from \"./urls\";\n\n/**\n * Base schema.org context and type\n */\ninterface BaseStructuredData {\n \"@context\": \"https://schema.org\";\n \"@type\": string;\n \"@id\"?: string;\n}\n\n/**\n * Person schema for authors\n * @see https://schema.org/Person\n */\nexport interface PersonSchema extends BaseStructuredData {\n \"@type\": \"Person\";\n name: string;\n description?: string;\n identifier?: string;\n image?: string;\n url?: string;\n sameAs?: string[];\n jobTitle?: string;\n affiliation?: OrganizationSchema;\n knowsAbout?: string[];\n additionalType?: string;\n}\n\n/**\n * Organization schema for blog sites\n * @see https://schema.org/Organization\n */\nexport interface OrganizationSchema extends BaseStructuredData {\n \"@type\": \"Organization\";\n name: string;\n description?: string;\n url?: string;\n logo?: string;\n sameAs?: string[];\n foundingDate?: string;\n location?: string;\n contactPoint?: {\n \"@type\": \"ContactPoint\";\n contactType: string;\n url?: string;\n email?: string;\n };\n}\n\n/**\n * BlogPosting schema for articles\n * @see https://schema.org/BlogPosting\n */\nexport interface BlogPostingSchema extends BaseStructuredData {\n \"@type\": \"BlogPosting\";\n headline: string;\n description?: string;\n image?: string | string[];\n datePublished: string;\n dateModified?: string;\n author?: PersonSchema | PersonSchema[];\n publisher: OrganizationSchema;\n mainEntityOfPage: {\n \"@type\": \"WebPage\";\n \"@id\": string;\n };\n keywords?: string | string[];\n wordCount?: number;\n timeRequired?: string; // ISO 8601 duration format (PT5M = 5 minutes)\n inLanguage?: string;\n isAccessibleForFree?: boolean;\n genre?: string | string[];\n about?: {\n \"@type\": \"Thing\";\n name: string;\n }[];\n mentions?: {\n \"@type\": \"Thing\";\n name: string;\n }[];\n}\n\n/**\n * WebSite schema for the blog home page\n * @see https://schema.org/WebSite\n */\nexport interface WebSiteSchema extends BaseStructuredData {\n \"@type\": \"WebSite\";\n name: string;\n description?: string;\n url: string;\n publisher: OrganizationSchema;\n inLanguage?: string;\n potentialAction?: {\n \"@type\": \"SearchAction\";\n target: {\n \"@type\": \"EntryPoint\";\n urlTemplate: string;\n };\n \"query-input\": string;\n };\n}\n\n/**\n * BreadcrumbList schema for navigation\n * @see https://schema.org/BreadcrumbList\n */\nexport interface BreadcrumbListSchema extends BaseStructuredData {\n \"@type\": \"BreadcrumbList\";\n itemListElement: {\n \"@type\": \"ListItem\";\n position: number;\n name: string;\n item: string;\n }[];\n}\n\n/**\n * Options for customizing structured data generation\n */\nexport interface StructuredDataOptions {\n /** Include optional properties like keywords, mentions, etc. */\n includeOptionalProperties?: boolean;\n /** Include search action in WebSite schema */\n includeSearchAction?: boolean;\n /** Custom domain override for URLs */\n customDomain?: string;\n /** Path prefix for blog URLs (e.g., '/blog', '/articles') */\n pathPrefix?: string;\n /** Language code (e.g., 'en-US') */\n language?: string;\n /** Whether content is free to access */\n isAccessibleForFree?: boolean;\n}\n\n/**\n * Generate comprehensive structured data for a blog article\n */\nexport function generateArticleStructuredData(\n article: PublishedArticle,\n options: StructuredDataOptions = {},\n): BlogPostingSchema {\n const {\n customDomain,\n pathPrefix = \"/blog\",\n language,\n isAccessibleForFree = true,\n includeOptionalProperties = true,\n } = options;\n\n const domain = customDomain ?? article.site.domain;\n const canonicalUrl = customDomain\n ? `https://${domain}${pathPrefix}/${article.slug}`\n : (article.meta.canonicalUrl ??\n `https://${domain}${pathPrefix}/${article.slug}`);\n\n // Generate author schema\n const authorSchema = article.author\n ? generateAuthorStructuredData(article.author, { customDomain, pathPrefix })\n : undefined;\n\n // Generate publisher schema\n const publisherSchema = generateOrganizationStructuredData(article.site, {\n customDomain,\n pathPrefix,\n });\n\n // Convert reading seconds to ISO 8601 duration\n const readingMinutes = Math.max(1, Math.ceil(article.readingSeconds / 60));\n const timeRequired = `PT${readingMinutes}M`;\n\n const schema: BlogPostingSchema = {\n \"@context\": \"https://schema.org\",\n \"@type\": \"BlogPosting\",\n \"@id\": `${canonicalUrl}#article`,\n headline: article.title,\n description: article.excerpt,\n datePublished: article.publishedAt,\n dateModified: article.updatedAt,\n author: authorSchema,\n publisher: publisherSchema,\n mainEntityOfPage: {\n \"@type\": \"WebPage\",\n \"@id\": canonicalUrl,\n },\n wordCount: article.wordCount,\n timeRequired,\n isAccessibleForFree,\n };\n\n // Add optional properties if enabled\n if (includeOptionalProperties) {\n // Featured image\n if (article.featuredImage) {\n schema.image = article.featuredImage;\n }\n\n // Keywords\n if (article.meta.keywords.length > 0) {\n schema.keywords = [...article.meta.keywords];\n }\n\n // Language\n if (language ?? article.site.locale) {\n schema.inLanguage = language ?? article.site.locale;\n }\n\n // Extract topics from tone adjectives or keywords for 'about' property\n if (article.site.toneAdjectives.length > 0) {\n schema.about = article.site.toneAdjectives.map((topic) => ({\n \"@type\": \"Thing\" as const,\n name: topic,\n }));\n }\n\n // Genre based on site description or tone\n if (article.site.toneAdjectives.length > 0) {\n schema.genre = [...article.site.toneAdjectives];\n }\n }\n\n return schema;\n}\n\n/**\n * Generate structured data for an author\n */\nexport function generateAuthorStructuredData(\n author: PublishedAuthor,\n options: StructuredDataOptions = {},\n): PersonSchema {\n const { customDomain, pathPrefix = \"/blog\" } = options;\n\n const schema: PersonSchema = {\n \"@context\": \"https://schema.org\",\n \"@type\": \"Person\",\n \"@id\": `#author-${author.id}`,\n name: author.name,\n identifier: author.id,\n };\n\n // Add optional properties\n if (author.bio) {\n schema.description = author.bio;\n }\n\n if (author.avatarUrl) {\n schema.image = author.avatarUrl;\n }\n\n const sameAs = [\n author.socialLinks?.website,\n author.socialLinks?.x,\n author.socialLinks?.linkedin,\n author.socialLinks?.github,\n ].filter((url): url is string => Boolean(url));\n\n if (sameAs.length > 0) {\n schema.sameAs = sameAs;\n }\n\n if (author.slug?.trim()) {\n const authorUrl = customDomain\n ? `https://${customDomain}${buildAuthorPath(pathPrefix, author.slug)}`\n : buildAuthorPath(pathPrefix, author.slug);\n schema.url = authorUrl;\n }\n\n // Additional type for guest authors\n if (author.isGuest) {\n schema.additionalType = \"GuestAuthor\";\n }\n\n // Add knowledge areas from tone adjectives\n if (author.toneAdjectives && author.toneAdjectives.length > 0) {\n schema.knowsAbout = [...author.toneAdjectives];\n }\n\n return schema;\n}\n\n/**\n * Generate structured data for a blog site organization\n */\nexport function generateOrganizationStructuredData(\n site: PublishedSite,\n options: StructuredDataOptions = {},\n): OrganizationSchema {\n const { customDomain, pathPrefix = \"/blog\" } = options;\n\n const domain = customDomain ?? site.domain;\n const siteUrl = `https://${domain}${pathPrefix}`;\n\n const schema: OrganizationSchema = {\n \"@context\": \"https://schema.org\",\n \"@type\": \"Organization\",\n \"@id\": `${siteUrl}#organization`,\n name: site.name,\n url: siteUrl,\n };\n\n // Add optional properties\n if (site.description?.trim()) {\n schema.description = site.description;\n }\n\n if (site.tagline?.trim()) {\n schema.description = schema.description\n ? `${schema.description}. ${site.tagline}`\n : site.tagline;\n }\n\n return schema;\n}\n\n/**\n * Generate structured data for the blog website\n */\nexport function generateWebSiteStructuredData(\n site: PublishedSite,\n options: StructuredDataOptions = {},\n): WebSiteSchema {\n const {\n customDomain,\n pathPrefix = \"/blog\",\n language,\n includeSearchAction = true,\n } = options;\n\n const domain = customDomain ?? site.domain;\n const siteUrl = `https://${domain}${pathPrefix}`;\n\n const publisherSchema = generateOrganizationStructuredData(site, options);\n\n const schema: WebSiteSchema = {\n \"@context\": \"https://schema.org\",\n \"@type\": \"WebSite\",\n \"@id\": `${siteUrl}#website`,\n name: site.name,\n url: siteUrl,\n publisher: publisherSchema,\n };\n\n // Add optional properties\n if (site.description?.trim()) {\n schema.description = site.description;\n }\n\n if (language ?? site.locale) {\n schema.inLanguage = language ?? site.locale;\n }\n\n // Add search action for better search engine integration\n if (includeSearchAction) {\n schema.potentialAction = {\n \"@type\": \"SearchAction\",\n target: {\n \"@type\": \"EntryPoint\",\n urlTemplate: `${siteUrl}?search={search_term_string}`,\n },\n \"query-input\": \"required name=search_term_string\",\n };\n }\n\n return schema;\n}\n\n/**\n * Generate breadcrumb structured data for navigation\n */\nexport function generateBreadcrumbStructuredData(\n breadcrumbs: Array<{ name: string; url: string }>,\n options: StructuredDataOptions = {},\n): BreadcrumbListSchema {\n const { customDomain } = options;\n\n return {\n \"@context\": \"https://schema.org\",\n \"@type\": \"BreadcrumbList\",\n itemListElement: breadcrumbs.map((crumb, index) => ({\n \"@type\": \"ListItem\" as const,\n position: index + 1,\n name: crumb.name,\n item:\n customDomain && !crumb.url.startsWith(\"http\")\n ? `https://${customDomain}${crumb.url}`\n : crumb.url,\n })),\n };\n}\n\n/**\n * Generate combined structured data for a complete article page\n */\nexport function generateCompleteArticleStructuredData(\n article: PublishedArticle,\n options: StructuredDataOptions = {},\n): Array<BlogPostingSchema | WebSiteSchema | BreadcrumbListSchema> {\n const schemas: Array<\n BlogPostingSchema | WebSiteSchema | BreadcrumbListSchema\n > = [];\n\n // Article schema\n schemas.push(generateArticleStructuredData(article, options));\n\n // Website schema\n schemas.push(generateWebSiteStructuredData(article.site, options));\n\n // Breadcrumb schema for article pages\n const pathPrefix = options.pathPrefix ?? \"/blog\";\n const breadcrumbs = [\n { name: \"Home\", url: \"/\" },\n { name: article.site.name, url: pathPrefix },\n { name: article.title, url: `${pathPrefix}/${article.slug}` },\n ];\n schemas.push(generateBreadcrumbStructuredData(breadcrumbs, options));\n\n return schemas;\n}\n\n/**\n * Generate structured data for the blog home page\n */\nexport function generateBlogHomeStructuredData(\n site: PublishedSite,\n featuredArticles: PublishedArticle[] = [],\n options: StructuredDataOptions = {},\n): Array<WebSiteSchema | BlogPostingSchema> {\n const schemas: Array<WebSiteSchema | BlogPostingSchema> = [];\n\n // Website schema for the home page\n schemas.push(generateWebSiteStructuredData(site, options));\n\n // Featured articles schemas (limit to first 3-5 for performance)\n if (featuredArticles.length > 0) {\n const articleSchemas = featuredArticles\n .slice(0, 5)\n .map((article) => generateArticleStructuredData(article, options));\n schemas.push(...articleSchemas);\n }\n\n return schemas;\n}\n\n/**\n * Validate structured data schema\n */\nexport function validateStructuredData(schema: BaseStructuredData): {\n isValid: boolean;\n errors: string[];\n} {\n const errors: string[] = [];\n\n // Check required fields\n if (!schema[\"@context\"]) {\n errors.push(\"Missing required @context property\");\n } else if (schema[\"@context\"] !== \"https://schema.org\") {\n errors.push(\"@context must be 'https://schema.org'\");\n }\n\n if (!schema[\"@type\"]) {\n errors.push(\"Missing required @type property\");\n }\n\n // Type-specific validations\n if (schema[\"@type\"] === \"BlogPosting\") {\n const blogSchema = schema as BlogPostingSchema;\n if (!blogSchema.headline) {\n errors.push(\"BlogPosting: Missing required headline\");\n }\n if (!blogSchema.datePublished) {\n errors.push(\"BlogPosting: Missing required datePublished\");\n }\n if (!blogSchema.author) {\n errors.push(\"BlogPosting: Missing required author\");\n }\n if (!blogSchema.publisher) {\n errors.push(\"BlogPosting: Missing required publisher\");\n }\n }\n\n if (schema[\"@type\"] === \"Person\") {\n const personSchema = schema as PersonSchema;\n if (!personSchema.name) {\n errors.push(\"Person: Missing required name\");\n }\n }\n\n if (schema[\"@type\"] === \"Organization\") {\n const orgSchema = schema as OrganizationSchema;\n if (!orgSchema.name) {\n errors.push(\"Organization: Missing required name\");\n }\n }\n\n return {\n isValid: errors.length === 0,\n errors,\n };\n}\n\n/**\n * Convert structured data to JSON-LD string for HTML embedding\n */\nexport function structuredDataToJsonLd(\n schema: BaseStructuredData | BaseStructuredData[],\n): string {\n return JSON.stringify(schema, null, 0);\n}\n\n/**\n * Create a React script element for JSON-LD structured data\n */\nexport function createStructuredDataScript(\n schema: BaseStructuredData | BaseStructuredData[],\n) {\n return {\n type: \"application/ld+json\",\n dangerouslySetInnerHTML: {\n __html: structuredDataToJsonLd(schema),\n },\n };\n}\n\n/**\n * Extract keywords from article content for structured data\n */\nexport function extractKeywordsFromArticle(\n article: PublishedArticle,\n): string[] {\n const keywords = new Set<string>();\n\n // Add meta keywords\n article.meta.keywords.forEach((keyword) => keywords.add(keyword));\n\n // Add site tone adjectives as topical keywords\n article.site.toneAdjectives.forEach((tone) => keywords.add(tone));\n\n // Add author tone adjectives\n if (article.author) {\n article.author.toneAdjectives.forEach((tone) => keywords.add(tone));\n }\n\n return Array.from(keywords);\n}\n\n/**\n * Error types for structured data operations\n */\nexport class StructuredDataError extends Error {\n constructor(\n message: string,\n public readonly code: string,\n public readonly details?: unknown,\n ) {\n super(message);\n this.name = \"StructuredDataError\";\n }\n}\n\n/**\n * Generate structured data with error handling\n */\nexport function safeGenerateArticleStructuredData(\n article: PublishedArticle,\n options: StructuredDataOptions = {},\n): { schema?: BlogPostingSchema; error?: StructuredDataError } {\n try {\n const schema = generateArticleStructuredData(article, options);\n const validation = validateStructuredData(schema);\n\n if (!validation.isValid) {\n return {\n error: new StructuredDataError(\n \"Generated schema validation failed\",\n \"VALIDATION_FAILED\",\n validation.errors,\n ),\n };\n }\n\n return { schema };\n } catch (error) {\n return {\n error: new StructuredDataError(\n \"Failed to generate structured data\",\n \"GENERATION_FAILED\",\n error,\n ),\n };\n }\n}\n","import { format, formatDistanceToNow } from \"date-fns\";\nimport type { CSSProperties } from \"react\";\n\nexport interface BlogTheme {\n accentColor?: string;\n accentHoverColor?: string;\n textAccentColor?: string;\n textAccentHoverColor?: string;\n accentBackgroundColor?: string;\n accentBorderColor?: string;\n}\n\nexport interface TocItem {\n id: string;\n text: string;\n level: 2 | 3;\n}\n\nexport interface ArticleDateMeta {\n publishedDateLabel: string;\n publishedRelativeLabel: string;\n updatedDateLabel: string;\n isUpdated: boolean;\n}\n\nexport interface TocItemState {\n isActive: boolean;\n ariaCurrent: \"location\" | undefined;\n}\n\nexport type BlogThemeStyle = CSSProperties & {\n \"--blog-accent\": string;\n \"--blog-accent-hover\": string;\n \"--blog-text-accent\": string;\n \"--blog-text-accent-hover\": string;\n \"--blog-accent-bg\": string;\n \"--blog-accent-border\": string;\n};\n\nexport const BLOG_PAGE_TITLE_GRADIENT_CLASS =\n \"bg-linear-to-br from-[var(--blog-accent-hover)] via-[var(--blog-text-accent)] to-fuchsia-200 bg-clip-text text-transparent\";\n\nconst DEFAULT_THEME: Required<BlogTheme> = {\n accentColor: \"hsl(var(--primary))\",\n accentHoverColor: \"hsl(var(--primary))\",\n textAccentColor: \"hsl(var(--primary))\",\n textAccentHoverColor: \"hsl(var(--primary))\",\n accentBackgroundColor: \"hsl(var(--primary) / 0.08)\",\n accentBorderColor: \"hsl(var(--primary) / 0.25)\",\n};\n\nexport function getBlogThemeStyle(theme: BlogTheme = {}): BlogThemeStyle {\n return {\n \"--blog-accent\": theme.accentColor ?? DEFAULT_THEME.accentColor,\n \"--blog-accent-hover\":\n theme.accentHoverColor ?? DEFAULT_THEME.accentHoverColor,\n \"--blog-text-accent\":\n theme.textAccentColor ?? theme.accentColor ?? DEFAULT_THEME.textAccentColor,\n \"--blog-text-accent-hover\":\n theme.textAccentHoverColor ??\n theme.accentHoverColor ??\n DEFAULT_THEME.textAccentHoverColor,\n \"--blog-accent-bg\":\n theme.accentBackgroundColor ?? DEFAULT_THEME.accentBackgroundColor,\n \"--blog-accent-border\":\n theme.accentBorderColor ?? DEFAULT_THEME.accentBorderColor,\n };\n}\n\nexport function formatArticleDateMeta(\n publishedAt: string,\n updatedAt: string,\n): ArticleDateMeta {\n const publishedDate = new Date(publishedAt);\n const updatedDate = new Date(updatedAt);\n\n return {\n publishedDateLabel: format(publishedDate, \"d MMMM yyyy\"),\n publishedRelativeLabel: formatDistanceToNow(publishedDate, {\n addSuffix: true,\n }),\n updatedDateLabel: format(updatedDate, \"d MMMM yyyy\"),\n isUpdated: updatedDate.getTime() !== publishedDate.getTime(),\n };\n}\n\nexport function extractTableOfContents(markdown: string): TocItem[] {\n const items: TocItem[] = [];\n let inFence = false;\n\n for (const line of markdown.split(\"\\n\")) {\n if (/^\\s*```/.test(line)) {\n inFence = !inFence;\n continue;\n }\n\n if (inFence) {\n continue;\n }\n\n const match = /^(#{2,3})\\s+(.+?)\\s*#*\\s*$/.exec(line);\n if (!match?.[1] || !match[2]) {\n continue;\n }\n\n const text = stripMarkdownInline(match[2]);\n if (!text) {\n continue;\n }\n\n items.push({\n id: slugifyHeading(text),\n text,\n level: match[1].length as 2 | 3,\n });\n }\n\n return items;\n}\n\nexport function formatTableOfContentsSummary(count: number): string {\n return `${count} ${count === 1 ? \"section\" : \"sections\"}`;\n}\n\nexport function normalizeReadingProgress(progress: number): number {\n if (!Number.isFinite(progress)) {\n return 0;\n }\n\n return Math.min(100, Math.max(0, progress));\n}\n\nexport function getTocItemState(\n itemId: string,\n activeItemId: string | null,\n): TocItemState {\n const isActive = itemId === activeItemId;\n\n return {\n isActive,\n ariaCurrent: isActive ? \"location\" : undefined,\n };\n}\n\nfunction stripMarkdownInline(value: string): string {\n return value\n .replace(/\\[([^\\]]+)\\]\\([^)]+\\)/g, \"$1\")\n .replace(/[*_`~]/g, \"\")\n .replace(/<[^>]+>/g, \"\")\n .replace(/\\s+/g, \" \")\n .trim();\n}\n\nfunction slugifyHeading(value: string): string {\n return value\n .toLowerCase()\n .replace(/[^a-z0-9\\s-]/g, \"\")\n .trim()\n .replace(/\\s+/g, \"-\")\n .replace(/-+/g, \"-\");\n}\n","\"use client\";\n\nimport { useState, useSyncExternalStore, type FormEvent } from \"react\";\nimport { ArrowUpRight, Check } from \"lucide-react\";\n\nimport { cn } from \"../lib/utils\";\nimport type { PublishedNewsletterSettings } from \"../types/contracts\";\n\nexport const NEWSLETTER_SUCCESS_MESSAGE =\n \"Thanks, you're on the list. We'll confirm before sending updates.\";\n\nexport interface NewsletterSignupProps {\n siteId: string;\n settings: PublishedNewsletterSettings;\n sourceSurface: \"blog_home\" | \"article\";\n sourceArticleSlug?: string;\n sourceUrl?: string;\n previewMode?: boolean;\n className?: string;\n}\n\nexport function NewsletterSignup({\n siteId,\n settings,\n sourceSurface,\n sourceArticleSlug,\n sourceUrl,\n previewMode = false,\n className,\n}: NewsletterSignupProps) {\n const [message, setMessage] = useState<string | null>(null);\n const [error, setError] = useState<string | null>(null);\n const [hasSubmitted, setHasSubmitted] = useState(false);\n const [isSubmitting, setIsSubmitting] = useState(false);\n const subscriptionKey = getSubscriptionStorageKey(siteId);\n const hasStoredSubscribed = useSyncExternalStore(\n subscribeToStoredSubscription,\n () => hasStoredSubscription(subscriptionKey),\n () => false,\n );\n const hasSubscribed = hasSubmitted || (!previewMode && hasStoredSubscribed);\n\n async function handleSubmit(event: FormEvent<HTMLFormElement>) {\n event.preventDefault();\n setError(null);\n setMessage(null);\n\n const formData = new FormData(event.currentTarget);\n const honeypot = getFormString(formData, \"company\");\n\n if (previewMode) {\n setMessage(NEWSLETTER_SUCCESS_MESSAGE);\n setHasSubmitted(true);\n event.currentTarget.reset();\n return;\n }\n\n setIsSubmitting(true);\n try {\n const response = await fetch(\n `${settings.captureBaseUrl.replace(/\\/$/, \"\")}/api/newsletter/subscribe`,\n {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({\n siteId: Number(siteId),\n publicSubscribeToken: settings.publicSubscribeToken,\n email: getFormString(formData, \"email\"),\n name: getOptionalFormString(formData, \"name\"),\n sourceSurface,\n sourceUrl: resolveSourceUrl(sourceUrl),\n sourceArticleSlug: sourceArticleSlug ?? null,\n honeypot,\n }),\n },\n );\n\n if (!response.ok) {\n throw new Error(\"Newsletter signup failed.\");\n }\n\n const result: unknown = await response.json().catch(() => null);\n const successMessage =\n getNewsletterResponseMessage(result) ?? NEWSLETTER_SUCCESS_MESSAGE;\n\n storeSubscription(subscriptionKey);\n setMessage(successMessage);\n setHasSubmitted(true);\n event.currentTarget.reset();\n } catch {\n setMessage(null);\n setError(\"Newsletter signup failed. Please try again.\");\n } finally {\n setIsSubmitting(false);\n }\n }\n\n return (\n <section\n className={cn(\n \"border-y border-[var(--blog-accent-border)] py-5 sm:py-6\",\n className,\n )}\n aria-labelledby={`newsletter-${sourceSurface}-title`}\n >\n <div className=\"grid gap-4 lg:grid-cols-[minmax(0,0.9fr)_minmax(0,1.4fr)] lg:items-end\">\n <div className=\"max-w-xl space-y-1\">\n <h2\n id={`newsletter-${sourceSurface}-title`}\n className=\"text-base leading-6 font-semibold\"\n >\n {settings.title}\n </h2>\n <p className=\"text-muted-foreground text-sm leading-6\">\n {settings.description}\n </p>\n </div>\n\n {hasSubscribed ? (\n <div\n className=\"flex items-start gap-3 text-sm leading-6 text-emerald-500\"\n role=\"status\"\n aria-live=\"polite\"\n >\n <span className=\"mt-0.5 inline-flex size-5 shrink-0 items-center justify-center rounded-full bg-emerald-500/15\">\n <Check className=\"size-3.5\" aria-hidden=\"true\" />\n </span>\n <p>{message ?? NEWSLETTER_SUCCESS_MESSAGE}</p>\n </div>\n ) : (\n <form onSubmit={handleSubmit} className=\"space-y-3\">\n <div className=\"grid gap-2 sm:grid-cols-[minmax(0,0.8fr)_minmax(0,1fr)_auto]\">\n <label\n className=\"sr-only\"\n htmlFor={`newsletter-name-${sourceSurface}`}\n >\n Name\n </label>\n <input\n id={`newsletter-name-${sourceSurface}`}\n name=\"name\"\n type=\"text\"\n autoComplete=\"name\"\n placeholder=\"Name\"\n className=\"border-input bg-background text-foreground placeholder:text-muted-foreground focus-visible:ring-ring min-h-10 rounded-md border px-3 py-2 text-sm focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-none\"\n />\n\n <label\n className=\"sr-only\"\n htmlFor={`newsletter-email-${sourceSurface}`}\n >\n Email\n </label>\n <input\n id={`newsletter-email-${sourceSurface}`}\n name=\"email\"\n type=\"email\"\n autoComplete=\"email\"\n placeholder=\"Email address\"\n required\n className=\"border-input bg-background text-foreground placeholder:text-muted-foreground focus-visible:ring-ring min-h-10 rounded-md border px-3 py-2 text-sm focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-none\"\n />\n\n <input\n type=\"text\"\n name=\"company\"\n tabIndex={-1}\n autoComplete=\"off\"\n aria-hidden=\"true\"\n className=\"hidden\"\n />\n\n <button\n type=\"submit\"\n disabled={isSubmitting}\n className=\"inline-flex min-h-10 w-full shrink-0 items-center justify-center gap-2 rounded-full bg-[var(--blog-accent)] px-5 py-2 text-sm font-semibold text-white transition-opacity hover:opacity-90 disabled:cursor-not-allowed disabled:opacity-60 sm:w-auto\"\n >\n {isSubmitting ? \"Submitting...\" : settings.buttonLabel}\n <ArrowUpRight className=\"size-4\" aria-hidden=\"true\" />\n </button>\n </div>\n\n {error && <p className=\"text-sm text-red-600\">{error}</p>}\n </form>\n )}\n </div>\n </section>\n );\n}\n\nfunction resolveSourceUrl(sourceUrl: string | undefined): string | null {\n if (sourceUrl?.startsWith(\"http://\") || sourceUrl?.startsWith(\"https://\")) {\n return sourceUrl;\n }\n\n if (typeof window !== \"undefined\") {\n return window.location.href;\n }\n\n return null;\n}\n\nfunction getFormString(formData: FormData, key: string): string {\n const value = formData.get(key);\n return typeof value === \"string\" ? value : \"\";\n}\n\nfunction getOptionalFormString(formData: FormData, key: string): string | null {\n const value = getFormString(formData, key).trim();\n if (value.length === 0) {\n return null;\n }\n\n return value;\n}\n\nfunction getSubscriptionStorageKey(siteId: string): string {\n return `bloggy_newsletter_subscribed_${siteId}`;\n}\n\nfunction hasStoredSubscription(key: string): boolean {\n if (typeof window === \"undefined\") {\n return false;\n }\n\n try {\n if (window.localStorage.getItem(key) === \"true\") {\n return true;\n }\n } catch {\n // Ignore storage failures; the subscription API remains the source of truth.\n }\n\n if (typeof document === \"undefined\") {\n return false;\n }\n\n return document.cookie\n .split(\";\")\n .some((cookie) => cookie.trim().startsWith(`${key}=true`));\n}\n\nfunction storeSubscription(key: string): void {\n if (typeof window !== \"undefined\") {\n try {\n window.localStorage.setItem(key, \"true\");\n } catch {\n // Ignore storage failures; users can still submit normally.\n }\n }\n\n if (typeof document !== \"undefined\") {\n document.cookie = `${key}=true; Max-Age=31536000; Path=/; SameSite=Lax`;\n }\n}\n\nfunction subscribeToStoredSubscription(callback: () => void): () => void {\n if (typeof window === \"undefined\") {\n return () => undefined;\n }\n\n window.addEventListener(\"storage\", callback);\n return () => window.removeEventListener(\"storage\", callback);\n}\n\nfunction getNewsletterResponseMessage(value: unknown): string | null {\n if (\n value &&\n typeof value === \"object\" &&\n \"message\" in value &&\n typeof value.message === \"string\"\n ) {\n return value.message;\n }\n\n return null;\n}\n","import React from \"react\";\nimport Link from \"next/link\";\nimport Image from \"next/image\";\nimport {\n type PublishedArticle,\n type PublishedAuthor,\n type PublishedNewsletterSettings,\n type PublishedSite,\n type PublishedTopic,\n} from \"../../types/contracts\";\nimport { cn } from \"../../lib/utils\";\nimport Pagination from \"../../components/Pagination\";\nimport {\n generateBlogHomeStructuredData,\n createStructuredDataScript,\n} from \"../../lib/structured-data\";\nimport {\n buildAuthorPath,\n buildBlogPath,\n normalizeBlogBasePath,\n} from \"../../lib/urls\";\nimport { formatDistanceToNow } from \"date-fns\";\nimport {\n BLOG_PAGE_TITLE_GRADIENT_CLASS,\n type BlogTheme,\n getBlogThemeStyle,\n} from \"../../lib/article-ui\";\nimport { NewsletterSignup } from \"../../components/NewsletterSignup\";\n\ninterface BlogHomePageProps {\n articles: PublishedArticle[];\n siteName?: string;\n siteTagline?: string;\n className?: string;\n /** Site data for structured data generation */\n site?: PublishedSite;\n /** Whether to include structured data */\n includeStructuredData?: boolean;\n /** Public path where this blog is mounted, e.g. \"/blog\" or \"/new-blog\". */\n basePath?: string;\n /** Pagination configuration */\n pagination?: {\n currentPage: number;\n totalPages: number;\n baseUrl?: string;\n };\n /** Optional theme values for host-site brand integration. */\n theme?: BlogTheme;\n /** Optional Bloggy-owned newsletter capture configuration. */\n newsletter?: PublishedNewsletterSettings;\n /** Render interactive preview success without persisting subscribers. */\n newsletterPreviewMode?: boolean;\n}\n\n/**\n * Blog home page component that displays a list of published articles.\n *\n * This component is designed to be used by customers who install the\n * @xexr/blog-platform package. It provides a clean, SEO-friendly\n * article listing with proper metadata.\n */\nexport default function BlogHomePage({\n articles,\n siteName,\n siteTagline,\n className,\n site,\n includeStructuredData = false,\n basePath = \"/blog\",\n pagination,\n theme,\n newsletter,\n newsletterPreviewMode = false,\n}: BlogHomePageProps) {\n const normalizedBasePath = normalizeBlogBasePath(basePath) || \"/\";\n const newsletterSettings = newsletter ?? site?.newsletter;\n const newsletterSiteId = site?.id ?? articles[0]?.site.id;\n\n return (\n <div\n style={getBlogThemeStyle(theme)}\n className={cn(\n \"blog-home-page container mx-auto max-w-5xl px-4 py-8 sm:px-6 sm:py-12 lg:px-8 lg:py-16\",\n className,\n )}\n >\n {/* Site Header */}\n {siteName && (\n <header className=\"blog-header mb-8 text-center sm:mb-12 lg:mb-16\">\n <h1\n className={cn(\n \"blog-title mb-2 text-3xl font-light tracking-tight text-balance sm:text-4xl lg:text-5xl\",\n BLOG_PAGE_TITLE_GRADIENT_CLASS,\n )}\n >\n {siteName}\n </h1>\n {siteTagline && (\n <p className=\"blog-tagline text-muted-foreground text-base sm:text-lg\">\n {siteTagline}\n </p>\n )}\n <nav\n aria-label=\"Browse blog\"\n className=\"mt-5 flex flex-wrap items-center justify-center gap-2 text-sm\"\n >\n <Link\n href={normalizedBasePath}\n aria-current=\"page\"\n className=\"rounded-full border border-[var(--blog-accent-border)] bg-[var(--blog-accent-bg)] px-3 py-1.5 font-medium text-[var(--blog-text-accent)] transition-colors hover:border-[var(--blog-text-accent)] hover:text-[var(--blog-text-accent-hover)] hover:no-underline\"\n >\n All articles\n </Link>\n <Link\n href={buildBlogPath(normalizedBasePath, \"topics\")}\n className=\"text-muted-foreground rounded-full border border-transparent px-3 py-1.5 font-medium transition-colors hover:border-[var(--blog-accent-border)] hover:text-[var(--blog-accent)] hover:no-underline\"\n >\n Topics\n </Link>\n <Link\n href={buildBlogPath(normalizedBasePath, \"authors\")}\n className=\"text-muted-foreground rounded-full border border-transparent px-3 py-1.5 font-medium transition-colors hover:border-[var(--blog-accent-border)] hover:text-[var(--blog-accent)] hover:no-underline\"\n >\n Authors\n </Link>\n </nav>\n </header>\n )}\n\n {/* Articles List */}\n <main className=\"articles-list\">\n {articles.length === 0 ? (\n <div className=\"no-articles text-muted-foreground py-16 text-center sm:py-24 lg:py-32\">\n <h2 className=\"mb-3 text-xl font-light sm:mb-4 sm:text-2xl lg:text-3xl\">\n No articles yet\n </h2>\n <p className=\"text-muted-foreground/70 mx-auto max-w-md text-base sm:text-lg\">\n This blog doesn&apos;t have any published articles yet.\n </p>\n </div>\n ) : (\n <div className=\"space-y-0\">\n {articles.map((article) => (\n <ArticlePreview\n key={article.id}\n article={article}\n basePath={normalizedBasePath}\n />\n ))}\n </div>\n )}\n\n {/* Pagination */}\n {pagination && pagination.totalPages > 1 && (\n <div className=\"pagination-wrapper mt-12\">\n <Pagination\n currentPage={pagination.currentPage}\n totalPages={pagination.totalPages}\n baseUrl={pagination.baseUrl ?? normalizedBasePath}\n className=\"justify-center\"\n />\n </div>\n )}\n </main>\n\n {newsletterSettings?.enabled && newsletterSiteId && (\n <NewsletterSignup\n siteId={newsletterSiteId}\n settings={newsletterSettings}\n sourceSurface=\"blog_home\"\n previewMode={newsletterPreviewMode}\n className=\"mt-10 sm:mt-12\"\n />\n )}\n\n {/* JSON-LD Structured Data */}\n {includeStructuredData &&\n site &&\n (() => {\n const structuredDataProps = createStructuredDataScript(\n generateBlogHomeStructuredData(site, articles.slice(0, 5), {\n pathPrefix: normalizedBasePath,\n }),\n );\n return (\n <script\n type={structuredDataProps.type}\n dangerouslySetInnerHTML={\n structuredDataProps.dangerouslySetInnerHTML\n }\n />\n );\n })()}\n </div>\n );\n}\n\n/**\n * Helper function to format reading time in minutes\n */\nfunction formatReadingTime(seconds: number): string {\n const minutes = Math.ceil(seconds / 60);\n return `${minutes} min read`;\n}\n\n/**\n * Individual article preview component for the blog listing.\n */\nfunction ArticlePreview({\n article,\n basePath,\n}: {\n article: PublishedArticle;\n basePath: string;\n}) {\n const articleUrl = buildBlogPath(basePath, article.slug);\n const formattedDate = formatDistanceToNow(new Date(article.publishedAt), {\n addSuffix: true,\n });\n const readingTime = formatReadingTime(article.readingSeconds);\n\n // Use the featured image URL provided by Bloggy (hosted on Bloggy's domain)\n const imageUrl = article.featuredImage;\n\n return (\n <article className=\"group border-border mb-6 block border-b pb-6 last:mb-0 last:border-b-0 last:pb-0 sm:mb-8 sm:pb-8\">\n {/* Mobile/Small Tablet: Vertical layout */}\n <div className=\"space-y-4 lg:hidden\">\n {imageUrl && (\n <Link\n href={articleUrl}\n className=\"focus-visible:ring-ring relative block aspect-[16/10] w-full overflow-hidden rounded-2xl focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-none\"\n aria-label={`Read article: ${article.title}`}\n >\n <Image\n src={imageUrl}\n alt={\n article.featuredImageAlt ??\n `Featured image for ${article.title}`\n }\n width={400}\n height={250}\n className=\"h-full w-full object-cover transition-transform duration-300 group-hover:scale-105\"\n />\n </Link>\n )}\n\n <div className=\"space-y-3\">\n <Link\n href={articleUrl}\n className=\"focus-visible:ring-ring block rounded-md hover:no-underline focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-none\"\n >\n <h2 className=\"text-lg leading-tight font-bold text-balance transition-colors group-hover:text-[var(--blog-accent)] sm:text-xl md:text-2xl\">\n {article.title}\n </h2>\n </Link>\n\n <div className=\"text-muted-foreground flex flex-wrap items-center gap-x-3 gap-y-1 text-sm\">\n {article.author && (\n <>\n <AuthorLink author={article.author} basePath={basePath} />\n <span className=\"text-border\">•</span>\n </>\n )}\n <time\n dateTime={article.publishedAt}\n className=\"font-medium\"\n aria-label={`Published ${formattedDate}`}\n >\n {formattedDate}\n </time>\n <span className=\"text-border\">•</span>\n <span className=\"font-medium\">{readingTime}</span>\n </div>\n\n {article.excerpt && (\n <p className=\"text-muted-foreground line-clamp-3 text-sm leading-relaxed sm:text-base\">\n {article.excerpt}\n </p>\n )}\n\n {(article.topics ?? []).length > 0 && (\n <div className=\"flex flex-wrap gap-2\">\n {(article.topics ?? []).map((topic) => (\n <TopicChip\n key={topic.id}\n topic={topic}\n basePath={basePath}\n />\n ))}\n </div>\n )}\n </div>\n </div>\n\n {/* Large Tablet/Desktop: Horizontal layout */}\n <div className=\"hidden items-start gap-6 lg:flex xl:gap-8\">\n {imageUrl && (\n <Link\n href={articleUrl}\n className=\"focus-visible:ring-ring relative block aspect-[16/10] w-64 shrink-0 overflow-hidden rounded-2xl focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-none xl:w-72\"\n aria-label={`Read article: ${article.title}`}\n >\n <Image\n src={imageUrl}\n alt={\n article.featuredImageAlt ??\n `Featured image for ${article.title}`\n }\n width={288}\n height={180}\n className=\"h-full w-full object-cover transition-transform duration-300 group-hover:scale-105\"\n />\n </Link>\n )}\n\n <div className=\"flex min-h-[180px] flex-1 flex-col justify-between space-y-4 xl:min-h-[200px]\">\n <div className=\"space-y-4\">\n <Link\n href={articleUrl}\n className=\"focus-visible:ring-ring block rounded-md hover:no-underline focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-none\"\n >\n <h2 className=\"text-2xl leading-tight font-bold text-balance transition-colors group-hover:text-[var(--blog-accent)] xl:text-3xl\">\n {article.title}\n </h2>\n </Link>\n\n {article.excerpt && (\n <p className=\"text-muted-foreground line-clamp-3 text-base leading-relaxed xl:text-lg\">\n {article.excerpt}\n </p>\n )}\n\n {(article.topics ?? []).length > 0 && (\n <div className=\"flex flex-wrap gap-2\">\n {(article.topics ?? []).map((topic) => (\n <TopicChip\n key={topic.id}\n topic={topic}\n basePath={basePath}\n />\n ))}\n </div>\n )}\n </div>\n\n <div className=\"text-muted-foreground flex flex-wrap items-center gap-x-3 gap-y-1 text-sm\">\n {article.author && (\n <>\n <AuthorLink author={article.author} basePath={basePath} />\n <span className=\"text-border\">•</span>\n </>\n )}\n <time\n dateTime={article.publishedAt}\n className=\"font-medium\"\n aria-label={`Published ${formattedDate}`}\n >\n {formattedDate}\n </time>\n <span className=\"text-border\">•</span>\n <span className=\"font-medium\">{readingTime}</span>\n </div>\n </div>\n </div>\n </article>\n );\n}\n\nfunction TopicChip({\n topic,\n basePath,\n}: {\n topic: PublishedTopic;\n basePath: string;\n}) {\n const className =\n \"rounded-full border border-[var(--blog-accent-border)] px-2.5 py-1 text-xs font-medium text-[var(--blog-text-accent)] transition-colors hover:border-[var(--blog-text-accent)] hover:text-[var(--blog-text-accent-hover)]\";\n const slug = topic.slug.trim();\n\n if (!slug) {\n return <span className={className}>{topic.name}</span>;\n }\n\n return (\n <Link href={buildBlogPath(basePath, `topics/${slug}`)} className={className}>\n {topic.name}\n </Link>\n );\n}\n\nfunction AuthorLink({\n author,\n basePath,\n}: {\n author: PublishedAuthor;\n basePath: string;\n}) {\n return (\n <Link\n href={buildAuthorPath(basePath, author.slug)}\n className=\"inline-flex items-center gap-2 font-medium transition-colors hover:text-[var(--blog-accent)] hover:no-underline\"\n >\n <AuthorAvatar author={author} size=\"sm\" />\n {author.name}\n </Link>\n );\n}\n\nfunction AuthorAvatar({\n author,\n size,\n}: {\n author: PublishedAuthor;\n size: \"sm\" | \"md\";\n}) {\n const sizeClass = size === \"md\" ? \"h-9 w-9 text-sm\" : \"h-6 w-6 text-xs\";\n const initials = getAuthorInitials(author.name);\n\n if (author.avatarUrl) {\n return (\n <Image\n src={author.avatarUrl}\n alt={author.name}\n width={size === \"md\" ? 36 : 24}\n height={size === \"md\" ? 36 : 24}\n className={cn(\"shrink-0 rounded-full object-cover\", sizeClass)}\n loading=\"lazy\"\n />\n );\n }\n\n return (\n <span\n className={cn(\n \"bg-muted inline-flex shrink-0 items-center justify-center rounded-full font-medium\",\n sizeClass,\n )}\n aria-hidden=\"true\"\n >\n {initials}\n </span>\n );\n}\n\nfunction getAuthorInitials(name: string): string {\n const initials = name\n .trim()\n .split(/\\s+/)\n .filter(Boolean)\n .slice(0, 2)\n .map((part) => part[0]?.toUpperCase())\n .join(\"\");\n\n return initials || \"?\";\n}\n\n/**\n * Generate metadata for the blog home page for SEO optimization.\n * This function should be used in the Next.js metadata API.\n */\nexport function generateBlogHomeMetadata(\n siteName?: string,\n siteDescription?: string,\n siteUrl?: string,\n pagination?: {\n currentPage: number;\n totalPages: number;\n },\n basePath = \"/blog\",\n) {\n const baseTitle = siteName ? `${siteName} - Blog` : \"Blog\";\n const title =\n pagination && pagination.currentPage > 1\n ? `${baseTitle} - Page ${pagination.currentPage}`\n : baseTitle;\n\n const description =\n siteDescription ?? \"Read our latest articles and insights.\";\n\n // Generate pagination URLs for SEO\n const baseUrl = normalizeBlogBasePath(basePath) || \"/\";\n const canonicalUrl = siteUrl\n ? `${siteUrl}${pagination && pagination.currentPage > 1 ? `${baseUrl}?page=${pagination.currentPage}` : baseUrl}`\n : undefined;\n\n const prevUrl =\n pagination && pagination.currentPage > 1\n ? siteUrl\n ? `${siteUrl}${pagination.currentPage === 2 ? baseUrl : `${baseUrl}?page=${pagination.currentPage - 1}`}`\n : undefined\n : undefined;\n\n const nextUrl =\n pagination && pagination.currentPage < pagination.totalPages\n ? siteUrl\n ? `${siteUrl}${baseUrl}?page=${pagination.currentPage + 1}`\n : undefined\n : undefined;\n\n return {\n title,\n description,\n openGraph: {\n title,\n description,\n type: \"website\",\n ...(siteUrl && { url: canonicalUrl }),\n },\n twitter: {\n card: \"summary_large_image\",\n title,\n description,\n },\n alternates: {\n ...(canonicalUrl && { canonical: canonicalUrl }),\n },\n other: {\n ...(prevUrl && { prev: prevUrl }),\n ...(nextUrl && { next: nextUrl }),\n },\n };\n}\n","import * as React from \"react\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"../../lib/utils\"\n\nconst badgeVariants = cva(\n \"inline-flex items-center rounded-md border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2\",\n {\n variants: {\n variant: {\n default:\n \"border-transparent bg-primary text-primary-foreground shadow hover:bg-primary/80\",\n secondary:\n \"border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80\",\n destructive:\n \"border-transparent bg-destructive text-destructive-foreground shadow hover:bg-destructive/80\",\n outline: \"text-foreground\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n },\n }\n)\n\nexport interface BadgeProps\n extends React.HTMLAttributes<HTMLDivElement>,\n VariantProps<typeof badgeVariants> {}\n\nfunction Badge({ className, variant, ...props }: BadgeProps) {\n return (\n <div className={cn(badgeVariants({ variant }), className)} {...props} />\n )\n}\n\nexport { Badge, badgeVariants }","import * as React from \"react\"\n\nimport { cn } from \"../../lib/utils\"\n\nfunction Card({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card\"\n className={cn(\n \"bg-card text-card-foreground flex flex-col gap-6 rounded-xl border py-6 shadow-sm\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-header\"\n className={cn(\n \"@container/card-header grid auto-rows-min grid-rows-[auto_auto] items-start gap-1.5 px-6 has-data-[slot=card-action]:grid-cols-[1fr_auto] [.border-b]:pb-6\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardTitle({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-title\"\n className={cn(\"leading-none font-semibold\", className)}\n {...props}\n />\n )\n}\n\nfunction CardDescription({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-description\"\n className={cn(\"text-muted-foreground text-sm\", className)}\n {...props}\n />\n )\n}\n\nfunction CardAction({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-action\"\n className={cn(\n \"col-start-2 row-span-2 row-start-1 self-start justify-self-end\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardContent({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-content\"\n className={cn(\"px-6\", className)}\n {...props}\n />\n )\n}\n\nfunction CardFooter({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-footer\"\n className={cn(\"flex items-center px-6 [.border-t]:pt-6\", className)}\n {...props}\n />\n )\n}\n\nexport {\n Card,\n CardHeader,\n CardFooter,\n CardTitle,\n CardAction,\n CardDescription,\n CardContent,\n}\n","\"use client\";\n\nimport React from \"react\";\nimport { Check, Copy, Share2 } from \"lucide-react\";\n\nimport { cn } from \"../lib/utils\";\n\ntype ClipboardLike = Pick<Clipboard, \"writeText\">;\n\ninterface CopyFallbackDocument {\n body: Pick<HTMLElement, \"appendChild\">;\n createElement: (tagName: \"textarea\") => HTMLTextAreaElement;\n execCommand: (commandId: \"copy\") => boolean;\n}\n\ninterface NavigatorLike {\n clipboard?: ClipboardLike;\n share?: (data: ShareData) => Promise<void>;\n}\n\ninterface ArticleTopActionsProps {\n title: string;\n url: string;\n className?: string;\n size?: \"sm\" | \"md\";\n}\n\nexport function resolveShareUrl(url: string, currentHref?: string): string {\n try {\n return new URL(url).href;\n } catch {\n if (!currentHref) return url;\n }\n\n try {\n return new URL(url, currentHref).href;\n } catch {\n return url;\n }\n}\n\nexport async function copyArticleLink(\n url: string,\n clipboard: ClipboardLike | undefined = globalThis.navigator?.clipboard,\n fallbackDocument: CopyFallbackDocument | undefined =\n typeof document === \"undefined\" ? undefined : document,\n): Promise<void> {\n if (clipboard) {\n try {\n await clipboard.writeText(url);\n return;\n } catch {\n // Fall back below for browser contexts that expose clipboard but deny it.\n }\n }\n\n if (!fallbackDocument) {\n throw new Error(\"Clipboard API is unavailable\");\n }\n\n const textarea = fallbackDocument.createElement(\"textarea\");\n textarea.value = url;\n textarea.setAttribute(\"readonly\", \"\");\n textarea.style.position = \"fixed\";\n textarea.style.left = \"-9999px\";\n\n fallbackDocument.body.appendChild(textarea);\n textarea.select();\n\n try {\n const copied = fallbackDocument.execCommand(\"copy\");\n if (!copied) {\n throw new Error(\"Copy command failed\");\n }\n } finally {\n textarea.remove();\n }\n}\n\nexport async function shareArticle(\n article: { title: string; url: string },\n navigatorLike: NavigatorLike | undefined = globalThis.navigator,\n): Promise<\"shared\" | \"copied\"> {\n if (navigatorLike?.share) {\n await navigatorLike.share({\n title: article.title,\n url: article.url,\n });\n return \"shared\";\n }\n\n await copyArticleLink(article.url, navigatorLike?.clipboard);\n return \"copied\";\n}\n\nexport default function ArticleTopActions({\n title,\n url,\n className,\n size = \"md\",\n}: ArticleTopActionsProps) {\n const [copied, setCopied] = React.useState(false);\n const [sharing, setSharing] = React.useState(false);\n const resolvedUrl = React.useMemo(\n () =>\n resolveShareUrl(\n url,\n typeof window === \"undefined\" ? undefined : window.location.href,\n ),\n [url],\n );\n\n React.useEffect(() => {\n if (!copied) return;\n\n const timeout = window.setTimeout(() => setCopied(false), 2000);\n return () => window.clearTimeout(timeout);\n }, [copied]);\n\n async function handleCopy() {\n await copyArticleLink(resolvedUrl);\n setCopied(true);\n }\n\n async function handleShare() {\n setSharing(true);\n try {\n const result = await shareArticle({ title, url: resolvedUrl });\n if (result === \"copied\") setCopied(true);\n } finally {\n setSharing(false);\n }\n }\n\n const buttonClassName =\n size === \"sm\"\n ? \"h-8 gap-1.5 px-2.5 text-xs\"\n : \"h-9 gap-2 px-3 text-sm\";\n const iconClassName = size === \"sm\" ? \"size-3.5\" : \"size-4\";\n\n return (\n <div\n className={cn(\n \"article-top-actions flex flex-wrap items-center justify-center gap-2\",\n className,\n )}\n >\n <button\n type=\"button\"\n aria-label=\"Copy article link\"\n onClick={handleCopy}\n className={cn(\n \"text-muted-foreground hover:text-foreground border-border inline-flex items-center justify-center rounded-full border font-medium transition-colors hover:border-[var(--blog-accent-border)] hover:bg-[var(--blog-accent-bg)]\",\n buttonClassName,\n )}\n >\n {copied ? (\n <Check className={iconClassName} aria-hidden=\"true\" />\n ) : (\n <Copy className={iconClassName} aria-hidden=\"true\" />\n )}\n <span>{copied ? \"Copied\" : \"Copy link\"}</span>\n </button>\n <button\n type=\"button\"\n aria-label=\"Share article\"\n onClick={handleShare}\n disabled={sharing}\n className={cn(\n \"text-muted-foreground hover:text-foreground border-border inline-flex items-center justify-center rounded-full border font-medium transition-colors hover:border-[var(--blog-accent-border)] hover:bg-[var(--blog-accent-bg)] disabled:cursor-wait disabled:opacity-60\",\n buttonClassName,\n )}\n >\n <Share2 className={iconClassName} aria-hidden=\"true\" />\n <span>Share</span>\n </button>\n </div>\n );\n}\n","/* eslint-disable @next/next/no-img-element */\n\nimport type React from \"react\";\n\nimport { cn } from \"../lib/utils\";\n\ntype ArticleImageProps = React.ImgHTMLAttributes<HTMLImageElement>;\n\nexport function ExpandableArticleImage({\n alt = \"\",\n className,\n src,\n ...props\n}: ArticleImageProps) {\n if (typeof src !== \"string\" || src.length === 0) {\n return <img alt={alt} className={className} {...props} />;\n }\n\n const previewId = `blog-image-preview-${hashImageSrc(src)}`;\n\n return (\n <>\n <a\n href={`#${previewId}`}\n className=\"group mx-auto block cursor-zoom-in rounded-2xl focus-visible:ring-2 focus-visible:ring-[var(--blog-text-accent)] focus-visible:ring-offset-2 focus-visible:outline-none\"\n aria-label={alt ? `Expand image: ${alt}` : \"Expand article image\"}\n >\n <img\n src={src}\n alt={alt}\n className={cn(\n \"mx-auto rounded-2xl border border-[var(--blog-accent-border)] shadow-[0_18px_60px_rgb(168_85_247_/_0.12)] transition-opacity group-hover:opacity-95\",\n className,\n )}\n {...props}\n />\n </a>\n\n <div\n id={previewId}\n className=\"invisible fixed inset-0 z-50 flex opacity-0 transition-opacity target:visible target:opacity-100\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label={alt ? `Image preview: ${alt}` : \"Image preview\"}\n >\n <a\n href=\"#article-content\"\n className=\"absolute inset-0 bg-black/85 backdrop-blur-sm\"\n aria-label=\"Close image preview\"\n />\n <div className=\"pointer-events-none relative z-10 flex min-h-screen w-full items-center justify-center p-4 sm:p-6\">\n <img\n src={src}\n alt={alt}\n className=\"pointer-events-auto h-[88vh] w-[94vw] rounded-3xl object-contain shadow-2xl\"\n />\n </div>\n <a\n href=\"#article-content\"\n className=\"absolute top-4 right-4 z-20 inline-flex size-10 items-center justify-center rounded-full border border-white/20 bg-black/50 text-xl leading-none text-white no-underline transition-colors hover:bg-white/10 focus-visible:ring-2 focus-visible:ring-white focus-visible:outline-none\"\n aria-label=\"Close image preview\"\n >\n ×\n </a>\n </div>\n </>\n );\n}\n\nfunction hashImageSrc(src: string): string {\n let hash = 0;\n\n for (let index = 0; index < src.length; index += 1) {\n hash = (hash << 5) - hash + src.charCodeAt(index);\n hash |= 0;\n }\n\n return Math.abs(hash).toString(36);\n}\n","\"use client\";\n\nimport { useEffect, useMemo } from \"react\";\n\nimport {\n formatTableOfContentsSummary,\n getTocItemState,\n type TocItem,\n} from \"../lib/article-ui\";\n\ninterface ArticleReadingProgressProps {\n items: TocItem[];\n contentId: string;\n variant: \"mobile\" | \"desktop\";\n showProgress?: boolean;\n}\n\nexport function ArticleReadingProgress({\n items,\n contentId,\n variant,\n showProgress = true,\n}: ArticleReadingProgressProps) {\n const activeItemId = items[0]?.id ?? null;\n const itemIds = useMemo(() => items.map((item) => item.id), [items]);\n\n return (\n <>\n <ArticleReadingProgressController\n contentId={contentId}\n itemIds={itemIds}\n />\n\n {showProgress && (\n <div\n data-blog-reading-progress={contentId}\n className=\"fixed inset-x-0 top-0 z-50 h-1 origin-left bg-[var(--blog-accent)] motion-safe:transition-transform\"\n style={{ transform: \"scaleX(0)\" }}\n role=\"progressbar\"\n aria-label=\"Reading progress\"\n aria-valuemin={0}\n aria-valuemax={100}\n aria-valuenow={0}\n suppressHydrationWarning\n />\n )}\n\n <ArticleTableOfContents\n items={items}\n activeItemId={activeItemId}\n variant={variant}\n />\n </>\n );\n}\n\nfunction ArticleReadingProgressController({\n contentId,\n itemIds,\n}: {\n contentId: string;\n itemIds: string[];\n}) {\n useEffect(() => {\n let animationFrameId = 0;\n let pendingHashItemId = decodeURIComponent(\n window.location.hash.replace(/^#/, \"\"),\n );\n\n const setActiveItem = (activeItemId: string | null) => {\n const tocLinks = Array.from(\n document.querySelectorAll<HTMLElement>(\"[data-blog-toc-link]\"),\n );\n\n for (const link of tocLinks) {\n const isActive = link.getAttribute(\"data-blog-toc-link\") === activeItemId;\n link.setAttribute(\"data-active\", isActive ? \"true\" : \"false\");\n if (isActive) {\n link.setAttribute(\"aria-current\", \"location\");\n } else {\n link.removeAttribute(\"aria-current\");\n }\n }\n };\n\n const updateScrollState = () => {\n const contentElement = document.getElementById(contentId);\n if (!contentElement) return;\n\n const progressElements = Array.from(\n document.querySelectorAll<HTMLElement>(\n `[data-blog-reading-progress=\"${contentId}\"]`,\n ),\n );\n const contentRect = contentElement.getBoundingClientRect();\n const scrollTop = window.scrollY;\n const contentTop = contentRect.top + scrollTop;\n const readableDistance = contentElement.offsetHeight - window.innerHeight;\n const nextProgress =\n readableDistance <= 0\n ? scrollTop >= contentTop\n ? 100\n : 0\n : ((scrollTop - contentTop) / readableDistance) * 100;\n const progress = normalizeProgress(nextProgress);\n\n for (const progressElement of progressElements) {\n progressElement.style.transform = `scaleX(${progress / 100})`;\n progressElement.setAttribute(\"aria-valuenow\", String(Math.round(progress)));\n }\n\n const headings = itemIds\n .map((id) => document.getElementById(id))\n .filter((heading): heading is HTMLElement => Boolean(heading));\n if (pendingHashItemId && itemIds.includes(pendingHashItemId)) {\n setActiveItem(pendingHashItemId);\n pendingHashItemId = \"\";\n return;\n }\n\n const activeOffset = Math.max(160, Math.round(window.innerHeight * 0.33));\n const activeHeading =\n headings\n .filter((heading) => heading.getBoundingClientRect().top <= activeOffset)\n .at(-1) ??\n headings[0] ??\n null;\n\n setActiveItem(activeHeading ? activeHeading.id : null);\n };\n\n const scheduleUpdate = () => {\n window.cancelAnimationFrame(animationFrameId);\n animationFrameId = window.requestAnimationFrame(updateScrollState);\n };\n\n const handleHashChange = () => {\n pendingHashItemId = decodeURIComponent(\n window.location.hash.replace(/^#/, \"\"),\n );\n scheduleUpdate();\n };\n\n scheduleUpdate();\n window.addEventListener(\"scroll\", scheduleUpdate, { passive: true });\n window.addEventListener(\"resize\", scheduleUpdate);\n window.addEventListener(\"hashchange\", handleHashChange);\n\n return () => {\n window.cancelAnimationFrame(animationFrameId);\n window.removeEventListener(\"scroll\", scheduleUpdate);\n window.removeEventListener(\"resize\", scheduleUpdate);\n window.removeEventListener(\"hashchange\", handleHashChange);\n };\n }, [contentId, itemIds]);\n\n return null;\n}\n\nfunction normalizeProgress(value: number): number {\n if (!Number.isFinite(value)) return 0;\n return Math.min(100, Math.max(0, value));\n}\n\nfunction ArticleTableOfContents({\n items,\n activeItemId,\n variant,\n}: {\n items: TocItem[];\n activeItemId: string | null;\n variant: \"mobile\" | \"desktop\";\n}) {\n if (items.length === 0) {\n return null;\n }\n\n const list = (\n <ul className=\"space-y-2 text-sm\">\n {items.map((item) => {\n const itemState = getTocItemState(item.id, activeItemId);\n\n return (\n <li key={item.id} className={item.level === 3 ? \"pl-4\" : undefined}>\n <a\n href={`#${item.id}`}\n aria-current={itemState.ariaCurrent}\n data-blog-toc-link={item.id}\n data-active={itemState.isActive ? \"true\" : \"false\"}\n suppressHydrationWarning\n className=\"text-muted-foreground hover:text-[var(--blog-text-accent)] data-[active=true]:border-[var(--blog-accent)] data-[active=true]:text-[var(--blog-text-accent)] block border-l-2 border-transparent pl-3 leading-snug transition-colors\"\n >\n {item.text}\n </a>\n </li>\n );\n })}\n </ul>\n );\n\n if (variant === \"mobile\") {\n return (\n <details className=\"group mb-6 rounded-2xl border border-[var(--blog-accent-border)] bg-[var(--blog-accent-bg)] lg:hidden\">\n <summary className=\"text-foreground flex cursor-pointer list-none items-center justify-between gap-3 px-4 py-3 text-sm font-semibold [&::-webkit-details-marker]:hidden\">\n <span>On this page</span>\n <span className=\"text-muted-foreground flex items-center gap-2 text-xs font-medium\">\n {formatTableOfContentsSummary(items.length)}\n <span\n className=\"text-[var(--blog-text-accent)] transition-transform group-open:rotate-180\"\n aria-hidden=\"true\"\n >\n ↓\n </span>\n </span>\n </summary>\n <nav\n aria-label=\"Table of contents\"\n className=\"border-t border-[var(--blog-accent-border)] px-4 py-4\"\n >\n {list}\n </nav>\n </details>\n );\n }\n\n return (\n <aside className=\"hidden lg:block\">\n <nav\n aria-label=\"Table of contents\"\n className=\"sticky top-24 max-h-[calc(100vh-8rem)] overflow-y-auto border-l border-border pl-5\"\n >\n <p className=\"text-muted-foreground mb-3 text-xs font-semibold tracking-wider uppercase\">\n On this page\n </p>\n {list}\n </nav>\n </aside>\n );\n}\n","import * as React from \"react\"\nimport * as SeparatorPrimitive from \"@radix-ui/react-separator\"\n\nimport { cn } from \"../../lib/utils\"\n\nconst Separator = React.forwardRef<\n React.ElementRef<typeof SeparatorPrimitive.Root>,\n React.ComponentPropsWithoutRef<typeof SeparatorPrimitive.Root>\n>(\n (\n { className, orientation = \"horizontal\", decorative = true, ...props },\n ref\n ) => (\n <SeparatorPrimitive.Root\n ref={ref}\n decorative={decorative}\n orientation={orientation}\n className={cn(\n \"shrink-0 bg-border\",\n orientation === \"horizontal\" ? \"h-[1px] w-full\" : \"h-full w-[1px]\",\n className\n )}\n {...props}\n />\n )\n)\nSeparator.displayName = SeparatorPrimitive.Root.displayName\n\nexport { Separator }","import remarkGfm from \"remark-gfm\";\nimport remarkToc from \"remark-toc\";\nimport rehypeSlug from \"rehype-slug\";\n\ninterface HastNode {\n type?: string;\n tagName?: string;\n value?: string;\n children?: HastNode[];\n}\n\nexport const articleMdxOptions = {\n mdxOptions: {\n remarkPlugins: [remarkToc, remarkGfm],\n rehypePlugins: [rehypeUnwrapStandaloneImages, rehypeSlug],\n },\n};\n\nexport function rehypeUnwrapStandaloneImages() {\n return (tree: HastNode) => {\n unwrapStandaloneImages(tree);\n };\n}\n\nfunction unwrapStandaloneImages(node: HastNode) {\n if (!node.children) {\n return;\n }\n\n node.children = node.children.flatMap((child) => {\n unwrapStandaloneImages(child);\n\n if (isStandaloneImageParagraph(child)) {\n return child.children?.filter(isMeaningfulNode) ?? [child];\n }\n\n return [child];\n });\n}\n\nfunction isStandaloneImageParagraph(node: HastNode): boolean {\n if (node.type !== \"element\" || node.tagName !== \"p\" || !node.children) {\n return false;\n }\n\n const meaningfulChildren = node.children.filter(isMeaningfulNode);\n return (\n meaningfulChildren.length === 1 && isImageLikeNode(meaningfulChildren[0])\n );\n}\n\nfunction isImageLikeNode(node: HastNode | undefined): boolean {\n if (node?.type !== \"element\") {\n return false;\n }\n\n if (node.tagName === \"img\") {\n return true;\n }\n\n if (node.tagName !== \"a\" || !node.children) {\n return false;\n }\n\n const meaningfulChildren = node.children.filter(isMeaningfulNode);\n return (\n meaningfulChildren.length === 1 && meaningfulChildren[0]?.tagName === \"img\"\n );\n}\n\nfunction isMeaningfulNode(node: HastNode): boolean {\n return node.type !== \"text\" || Boolean(node.value?.trim());\n}\n","import React from \"react\";\nimport Image from \"next/image\";\nimport Link from \"next/link\";\nimport { MDXRemote } from \"next-mdx-remote-client/rsc\";\nimport {\n type PublishedArticle,\n type PublishedAuthor,\n type PublishedNewsletterSettings,\n} from \"../../../types/contracts\";\nimport { cn } from \"../../../lib/utils\";\nimport { ArrowLeft, ArrowUpRight, Globe, Mail } from \"lucide-react\";\nimport { FaGithub, FaLinkedinIn, FaXTwitter } from \"react-icons/fa6\";\nimport { Badge } from \"../../../components/ui/badge\";\nimport { Card, CardContent } from \"../../../components/ui/card\";\nimport ArticleTopActions from \"../../../components/ArticleTopActions\";\nimport { ExpandableArticleImage } from \"../../../components/ExpandableArticleImage\";\nimport { ArticleReadingProgress } from \"../../../components/ArticleReadingProgress\";\nimport { Separator } from \"../../../components/ui/separator\";\nimport {\n generateCompleteArticleStructuredData,\n createStructuredDataScript,\n} from \"../../../lib/structured-data\";\nimport { articleMdxOptions } from \"../../../lib/mdx\";\nimport {\n buildAuthorPath,\n buildBlogPath,\n normalizeBlogBasePath,\n} from \"../../../lib/urls\";\nimport { NewsletterSignup } from \"../../../components/NewsletterSignup\";\nimport {\n BLOG_PAGE_TITLE_GRADIENT_CLASS,\n type BlogTheme,\n extractTableOfContents,\n formatArticleDateMeta,\n getBlogThemeStyle,\n} from \"../../../lib/article-ui\";\n\nexport interface ArticlePageProps {\n article: PublishedArticle;\n className?: string;\n /** Optional navigation links */\n navigation?: {\n backToHome?: {\n url: string;\n label?: string;\n };\n previousArticle?: {\n url: string;\n title: string;\n featuredImage?: string;\n featuredImageAlt?: string;\n };\n nextArticle?: {\n url: string;\n title: string;\n featuredImage?: string;\n featuredImageAlt?: string;\n };\n };\n /** Public path where this blog is mounted, e.g. \"/blog\" or \"/new-blog\". */\n basePath?: string;\n /** Optional theme values for host-site brand integration. */\n theme?: BlogTheme;\n /** Optional post-article CTA supplied by the host site. */\n postArticleCta?: {\n title: string;\n description?: string;\n href: string;\n label: string;\n };\n /** Optional Bloggy-owned newsletter capture configuration. */\n newsletter?: PublishedNewsletterSettings;\n /** Render interactive preview success without persisting subscribers. */\n newsletterPreviewMode?: boolean;\n /** Optional related articles supplied by the host site. */\n relatedArticles?: PublishedArticle[];\n /** Whether to render static article share links. */\n showShareLinks?: boolean;\n}\n\n/**\n * Individual article page component that displays full article content.\n *\n * This component is designed to be used by customers who install the\n * @xexr/blog-platform package. It provides a complete article view\n * with proper SEO metadata, structured data, and accessibility features.\n */\n/**\n * Helper function to format reading time in minutes\n */\nfunction formatReadingTime(seconds: number): string {\n const minutes = Math.ceil(seconds / 60);\n return `${minutes} min read`;\n}\n\nfunction formatCreditUrl(url: string): string {\n try {\n return new URL(url).hostname.replace(/^www\\./, \"\");\n } catch {\n return url;\n }\n}\n\nfunction FeaturedImageCredit({\n creditText,\n creditUrl,\n}: {\n creditText?: string;\n creditUrl?: string;\n}) {\n if (!creditText && !creditUrl) {\n return null;\n }\n\n const label = creditText ?? formatCreditUrl(creditUrl ?? \"\");\n\n return (\n <span>\n Credit:{\" \"}\n {creditUrl ? (\n <a\n href={creditUrl}\n target=\"_blank\"\n rel=\"noreferrer\"\n className=\"underline underline-offset-2 transition-colors hover:text-[var(--blog-text-accent)]\"\n >\n {label}\n </a>\n ) : (\n label\n )}\n </span>\n );\n}\n\nexport default function ArticlePage({\n article,\n className,\n navigation,\n basePath = \"/blog\",\n theme,\n postArticleCta,\n newsletter,\n newsletterPreviewMode = false,\n relatedArticles = [],\n showShareLinks = true,\n}: ArticlePageProps) {\n const normalizedBasePath = normalizeBlogBasePath(basePath) || \"/\";\n const dateMeta = formatArticleDateMeta(\n article.publishedAt,\n article.updatedAt,\n );\n const readingTime = formatReadingTime(article.readingSeconds);\n const tocItems = extractTableOfContents(article.content);\n const articleUrl =\n article.meta.canonicalUrl ??\n buildBlogPath(normalizedBasePath, article.slug);\n const newsletterSettings = newsletter ?? article.site.newsletter;\n\n // Use the featured image URL provided by Bloggy (hosted on Bloggy's domain)\n const imageUrl = article.featuredImage;\n const hasFeaturedImageMeta = Boolean(\n article.featuredImageCaption ??\n article.featuredImageCreditText ??\n article.featuredImageCreditUrl,\n );\n\n return (\n <article\n style={getBlogThemeStyle(theme)}\n className={cn(\n \"article-page mx-auto max-w-6xl px-4 py-6 pb-12 sm:px-6 sm:py-8 sm:pb-16 lg:px-8 lg:py-12 lg:pb-24\",\n className,\n )}\n >\n {/* Navigation */}\n {navigation?.backToHome && (\n <header className=\"mx-auto mb-8 max-w-4xl sm:mb-12 lg:mb-16\">\n <Link\n href={navigation.backToHome.url}\n className=\"text-muted-foreground group focus-visible:ring-ring inline-flex touch-manipulation items-center space-x-2 rounded-md px-2 py-1 transition-colors hover:text-[var(--blog-accent)] focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-none sm:space-x-3\"\n aria-label={navigation.backToHome.label ?? \"Return to blog\"}\n >\n <ArrowLeft\n className=\"h-4 w-4 transition-transform group-hover:-translate-x-1 sm:h-5 sm:w-5\"\n aria-hidden=\"true\"\n />\n <span className=\"text-sm font-medium sm:text-base\">\n <span className=\"hidden sm:inline\">\n {navigation.backToHome.label ?? \"Back to all articles\"}\n </span>\n <span className=\"sm:hidden\">Back</span>\n </span>\n </Link>\n </header>\n )}\n\n <style>{`\n .article-content figure > p {\n margin-top: 0 !important;\n margin-bottom: 0 !important;\n }\n\n .article-content figure figcaption {\n margin-top: 0.5rem !important;\n text-align: center;\n font-size: 0.875rem !important;\n line-height: 1.35 !important;\n color: hsl(var(--muted-foreground));\n }\n\n .article-content figure figcaption .blog-image-credit {\n display: block;\n margin-top: 0.25rem;\n font-size: 0.75rem;\n line-height: 1.25;\n letter-spacing: 0.025em;\n opacity: 0.8;\n }\n\n .article-content figure figcaption > span:not(.blog-image-credit) {\n margin-left: 0.5rem;\n padding-left: 0.5rem;\n border-left: 1px solid var(--blog-accent-border);\n font-size: 0.75rem;\n letter-spacing: 0.025em;\n opacity: 0.8;\n }\n\n .article-content figure figcaption a {\n color: inherit;\n text-decoration-line: underline;\n text-underline-offset: 0.18em;\n }\n `}</style>\n\n {/* Article Header */}\n <header className=\"article-header mx-auto mb-6 max-w-4xl space-y-4 text-center sm:mb-8 sm:space-y-6 lg:mb-12 lg:space-y-8\">\n {/* Title */}\n <h1\n className={cn(\n \"article-title px-4 text-2xl leading-tight font-light tracking-tight text-balance sm:px-0 sm:text-3xl md:text-4xl lg:text-5xl xl:text-6xl\",\n BLOG_PAGE_TITLE_GRADIENT_CLASS,\n )}\n >\n {article.title}\n </h1>\n\n {/* Excerpt */}\n {article.excerpt && (\n <p className=\"article-excerpt text-muted-foreground mx-auto mt-6 max-w-[42rem] px-4 text-lg leading-relaxed text-balance sm:mt-8 sm:max-w-[46rem] sm:px-0 sm:text-xl md:max-w-[52rem] md:text-2xl lg:max-w-4xl lg:text-2xl\">\n {article.excerpt}\n </p>\n )}\n\n {/* Article Metadata */}\n <div className=\"article-meta text-muted-foreground flex flex-col items-center gap-2 text-sm sm:gap-3 sm:text-base\">\n {article.author && (\n <div className=\"flex items-center gap-2\">\n <span className=\"sr-only\">Author</span>\n <Link\n href={buildAuthorPath(normalizedBasePath, article.author.slug)}\n className=\"inline-flex items-center gap-2 font-medium transition-colors hover:text-[var(--blog-accent)] hover:no-underline\"\n >\n <AuthorAvatar author={article.author} size=\"md\" />\n {article.author.name}\n </Link>\n {article.author.isGuest && (\n <Badge variant=\"outline\" className=\"text-xs\">\n Guest Author\n </Badge>\n )}\n </div>\n )}\n\n <div className=\"flex flex-wrap items-center justify-center gap-x-3 gap-y-1\">\n <time\n dateTime={article.publishedAt}\n className=\"font-medium\"\n aria-label={`Published ${dateMeta.publishedDateLabel}`}\n >\n Published {dateMeta.publishedDateLabel}\n </time>\n <span className=\"text-border\">•</span>\n <span className=\"font-medium\">\n {dateMeta.publishedRelativeLabel}\n </span>\n <span className=\"text-border\">•</span>\n <span className=\"font-medium\">{readingTime}</span>\n </div>\n\n {dateMeta.isUpdated && (\n <time dateTime={article.updatedAt} className=\"text-xs\">\n Updated {dateMeta.updatedDateLabel}\n </time>\n )}\n\n {showShareLinks && (\n <ArticleTopActions\n title={article.title}\n url={articleUrl}\n size=\"sm\"\n />\n )}\n\n <div className=\"bg-border h-px w-6 sm:w-8\" aria-hidden=\"true\"></div>\n\n {(article.topics ?? []).length > 0 ? (\n <nav\n aria-label=\"Article topics\"\n className=\"flex flex-wrap justify-center gap-2\"\n >\n {(article.topics ?? []).map((topic) => (\n <Link\n key={topic.id}\n href={buildBlogPath(\n (navigation?.backToHome?.url ?? \"/blog\").replace(/\\/$/, \"\"),\n `topics/${topic.slug}`,\n )}\n className=\"rounded-full border border-[var(--blog-accent-border)] bg-[var(--blog-accent-bg)] px-3 py-1 text-xs font-medium text-[var(--blog-text-accent)] transition-colors hover:border-[var(--blog-text-accent)] hover:text-[var(--blog-text-accent-hover)]\"\n >\n {topic.name}\n </Link>\n ))}\n </nav>\n ) : (\n <span\n className=\"text-xs tracking-wider uppercase sm:text-sm\"\n role=\"text\"\n >\n From {article.site.name}\n </span>\n )}\n </div>\n </header>\n\n {/* Featured Image */}\n {imageUrl && (\n <figure className=\"article-featured-image mx-auto my-8 w-full max-w-4xl sm:my-12 lg:my-16\">\n <div className=\"aspect-[16/9] overflow-hidden rounded-3xl border border-[var(--blog-accent-border)] shadow-[0_24px_80px_rgb(168_85_247_/_0.14)]\">\n <Image\n src={imageUrl}\n alt={\n article.featuredImageAlt ??\n `Featured image for ${article.title}`\n }\n className=\"h-full w-full object-cover\"\n width={800}\n height={450}\n priority\n />\n </div>\n\n {hasFeaturedImageMeta && (\n <figcaption className=\"text-muted-foreground mt-3 space-y-1 px-2 text-center text-sm leading-relaxed sm:px-0\">\n {article.featuredImageCaption && (\n <p>{article.featuredImageCaption}</p>\n )}\n {(article.featuredImageCreditText ??\n article.featuredImageCreditUrl) && (\n <p className=\"text-xs\">\n <FeaturedImageCredit\n creditText={article.featuredImageCreditText}\n creditUrl={article.featuredImageCreditUrl}\n />\n </p>\n )}\n </figcaption>\n )}\n </figure>\n )}\n\n {/* Article Content */}\n <div\n id=\"article-content\"\n className=\"article-content mx-auto grid max-w-6xl grid-cols-1 gap-8 lg:grid-cols-[minmax(0,1fr)_14rem] lg:gap-12\"\n >\n <div className=\"min-w-0\">\n <ArticleReadingProgress\n items={tocItems}\n contentId=\"article-body\"\n variant=\"mobile\"\n />\n\n <div\n id=\"article-body\"\n className=\"prose prose-sm sm:prose-base lg:prose-lg xl:prose-xl prose-gray dark:prose-invert prose-headings:scroll-mt-20 prose-headings:font-light prose-headings:text-balance prose-headings:text-[var(--blog-text-accent)] prose-h1:text-2xl sm:prose-h1:text-3xl lg:prose-h1:text-4xl prose-h2:text-xl sm:prose-h2:text-2xl lg:prose-h2:text-3xl prose-h3:text-lg sm:prose-h3:text-xl lg:prose-h3:text-2xl prose-p:leading-relaxed prose-p:text-pretty prose-a:text-[var(--blog-text-accent)] prose-a:transition-colors hover:prose-a:text-[var(--blog-text-accent-hover)] [&_figure>p]:!my-0 [&_figcaption]:!mt-2 [&_figcaption]:text-center [&_figcaption]:!text-sm [&_figcaption]:!leading-snug [&_figcaption]:text-muted-foreground [&_figcaption_.blog-image-credit]:mt-1 [&_figcaption_.blog-image-credit]:block [&_figcaption_.blog-image-credit]:text-xs [&_figcaption_.blog-image-credit]:tracking-wide [&_figcaption_.blog-image-credit]:text-muted-foreground/80 [&_figcaption>span:not(.blog-image-credit)]:ml-2 [&_figcaption>span:not(.blog-image-credit)]:border-l [&_figcaption>span:not(.blog-image-credit)]:border-[var(--blog-accent-border)] [&_figcaption>span:not(.blog-image-credit)]:pl-2 [&_figcaption>span:not(.blog-image-credit)]:text-xs [&_figcaption>span:not(.blog-image-credit)]:tracking-wide [&_figcaption>span:not(.blog-image-credit)]:text-muted-foreground/80 max-w-none\"\n >\n <MDXRemote\n source={article.content}\n options={articleMdxOptions}\n components={{ img: ExpandableArticleImage }}\n />\n </div>\n </div>\n\n <ArticleReadingProgress\n items={tocItems}\n contentId=\"article-body\"\n variant=\"desktop\"\n showProgress={false}\n />\n </div>\n\n {/* Author Bio */}\n {article.author?.bio && (\n <div id=\"about-author\" className=\"author-bio mx-auto mt-12 max-w-4xl\">\n <Separator className=\"mb-8\" />\n <Card className=\"border-[var(--blog-accent-border)] bg-[var(--blog-accent-bg)]\">\n <CardContent className=\"flex flex-col gap-4 p-5 sm:flex-row sm:items-start sm:p-6\">\n <div className=\"shrink-0\">\n <AuthorAvatar author={article.author} size=\"lg\" />\n </div>\n <div className=\"min-w-0 flex-1 space-y-2\">\n <div className=\"flex flex-col gap-2 sm:flex-row sm:items-start sm:justify-between\">\n <div className=\"min-w-0\">\n <p className=\"text-muted-foreground text-sm font-medium\">\n Written by\n </p>\n <h2 className=\"text-foreground flex flex-wrap items-center gap-2 text-xl font-semibold\">\n <Link\n href={buildAuthorPath(\n normalizedBasePath,\n article.author.slug,\n )}\n className=\"transition-colors hover:text-[var(--blog-accent)] hover:no-underline\"\n >\n {article.author.name}\n </Link>\n {article.author.isGuest && (\n <Badge variant=\"outline\" className=\"text-xs\">\n Guest Author\n </Badge>\n )}\n </h2>\n </div>\n <AuthorSocialLinks author={article.author} />\n </div>\n <p className=\"text-muted-foreground leading-relaxed\">\n {article.author.bio}\n </p>\n </div>\n </CardContent>\n </Card>\n </div>\n )}\n\n {((postArticleCta ?? false) ||\n (newsletterSettings?.enabled ?? false) ||\n showShareLinks ||\n relatedArticles.length > 0) && (\n <div className=\"mx-auto mt-12 max-w-4xl space-y-8\">\n <Separator />\n {postArticleCta && <PostArticleCta cta={postArticleCta} />}\n {newsletterSettings?.enabled && (\n <NewsletterSignup\n siteId={article.site.id}\n settings={newsletterSettings}\n sourceSurface=\"article\"\n sourceArticleSlug={article.slug}\n sourceUrl={articleUrl}\n previewMode={newsletterPreviewMode}\n />\n )}\n {showShareLinks && (\n <ArticleShareLinks title={article.title} url={articleUrl} />\n )}\n {relatedArticles.length > 0 && (\n <RelatedArticles\n articles={relatedArticles.slice(0, 3)}\n basePath={normalizedBasePath}\n />\n )}\n </div>\n )}\n\n {/* Article Navigation */}\n {(Boolean(navigation?.previousArticle) ||\n Boolean(navigation?.nextArticle)) && (\n <nav className=\"article-nav mx-auto mt-12 max-w-4xl\">\n <Separator className=\"mb-8\" />\n <div className=\"grid grid-cols-1 gap-4 md:grid-cols-2\">\n {navigation?.previousArticle && (\n <Card className=\"group cursor-pointer transition-colors hover:border-[var(--blog-accent-border)] hover:bg-[var(--blog-accent-bg)]\">\n <Link href={navigation.previousArticle.url} className=\"block\">\n {navigation.previousArticle.featuredImage && (\n <ArticleCardImage\n src={navigation.previousArticle.featuredImage}\n alt={\n navigation.previousArticle.featuredImageAlt ??\n `Featured image for ${navigation.previousArticle.title}`\n }\n />\n )}\n <CardContent className=\"p-4\">\n <div className=\"text-muted-foreground mb-2 text-sm font-medium\">\n ← Previous Article\n </div>\n <div className=\"text-foreground transition-colors group-hover:text-[var(--blog-text-accent)]\">\n {navigation.previousArticle.title}\n </div>\n </CardContent>\n </Link>\n </Card>\n )}\n {navigation?.nextArticle && (\n <Card\n className={cn(\n \"group cursor-pointer transition-colors hover:border-[var(--blog-accent-border)] hover:bg-[var(--blog-accent-bg)]\",\n !navigation?.previousArticle && \"md:col-start-2\",\n )}\n >\n <Link href={navigation.nextArticle.url} className=\"block\">\n {navigation.nextArticle.featuredImage && (\n <ArticleCardImage\n src={navigation.nextArticle.featuredImage}\n alt={\n navigation.nextArticle.featuredImageAlt ??\n `Featured image for ${navigation.nextArticle.title}`\n }\n />\n )}\n <CardContent className=\"p-4 md:text-right\">\n <div className=\"text-muted-foreground mb-2 text-sm font-medium\">\n Next Article →\n </div>\n <div className=\"text-foreground transition-colors group-hover:text-[var(--blog-text-accent)]\">\n {navigation.nextArticle.title}\n </div>\n </CardContent>\n </Link>\n </Card>\n )}\n </div>\n </nav>\n )}\n\n {/* JSON-LD Structured Data */}\n {(() => {\n const structuredDataProps = createStructuredDataScript(\n generateCompleteArticleStructuredData(article, {\n pathPrefix: normalizedBasePath,\n }),\n );\n return (\n <script\n type={structuredDataProps.type}\n dangerouslySetInnerHTML={\n structuredDataProps.dangerouslySetInnerHTML\n }\n />\n );\n })()}\n </article>\n );\n}\n\nfunction AuthorAvatar({\n author,\n size,\n}: {\n author: PublishedAuthor;\n size: \"md\" | \"lg\";\n}) {\n const sizeClass = size === \"lg\" ? \"h-12 w-12 text-base\" : \"h-9 w-9 text-sm\";\n const initials = getAuthorInitials(author.name);\n\n if (author.avatarUrl) {\n return (\n <Image\n src={author.avatarUrl}\n alt={author.name}\n width={size === \"lg\" ? 48 : 36}\n height={size === \"lg\" ? 48 : 36}\n className={cn(\"shrink-0 rounded-full object-cover\", sizeClass)}\n loading=\"lazy\"\n />\n );\n }\n\n return (\n <span\n className={cn(\n \"bg-muted text-muted-foreground inline-flex shrink-0 items-center justify-center rounded-full font-medium\",\n sizeClass,\n )}\n aria-hidden=\"true\"\n >\n {initials}\n </span>\n );\n}\n\ninterface AuthorSocialLinkView {\n key: string;\n href: string;\n label: string;\n external: boolean;\n icon: React.ReactNode;\n}\n\nfunction AuthorSocialLinks({ author }: { author: PublishedAuthor }) {\n const links = getAuthorSocialLinks(author);\n if (links.length === 0) return null;\n\n return (\n <div className=\"flex flex-wrap items-center gap-1 sm:justify-end\">\n {links.map((link) => (\n <a\n key={link.key}\n href={link.href}\n target={link.external ? \"_blank\" : undefined}\n rel={link.external ? \"noopener noreferrer\" : undefined}\n aria-label={`${author.name} ${link.label}`}\n className=\"text-muted-foreground hover:bg-background/60 hover:text-foreground inline-flex size-7 items-center justify-center rounded-full transition-colors\"\n >\n {link.icon}\n </a>\n ))}\n </div>\n );\n}\n\nfunction getAuthorSocialLinks(author: PublishedAuthor): AuthorSocialLinkView[] {\n const links = author.socialLinks;\n if (!links) return [];\n\n const socialLinks: Array<AuthorSocialLinkView | false | undefined> = [\n links.website\n ? {\n key: \"website\",\n href: links.website,\n label: \"website\",\n external: true,\n icon: <Globe className=\"size-4\" aria-hidden=\"true\" />,\n }\n : undefined,\n links.x\n ? {\n key: \"x\",\n href: links.x,\n label: \"on X\",\n external: true,\n icon: <FaXTwitter className=\"size-4\" aria-hidden=\"true\" />,\n }\n : undefined,\n links.linkedin\n ? {\n key: \"linkedin\",\n href: links.linkedin,\n label: \"on LinkedIn\",\n external: true,\n icon: <FaLinkedinIn className=\"size-4\" aria-hidden=\"true\" />,\n }\n : undefined,\n links.github\n ? {\n key: \"github\",\n href: links.github,\n label: \"on GitHub\",\n external: true,\n icon: <FaGithub className=\"size-4\" aria-hidden=\"true\" />,\n }\n : undefined,\n links.email\n ? {\n key: \"email\",\n href: `mailto:${links.email}`,\n label: \"email\",\n external: false,\n icon: <Mail className=\"size-4\" aria-hidden=\"true\" />,\n }\n : undefined,\n ];\n\n return socialLinks.filter((link): link is AuthorSocialLinkView =>\n Boolean(link),\n );\n}\n\nfunction getAuthorInitials(name: string): string {\n const initials = name\n .trim()\n .split(/\\s+/)\n .filter(Boolean)\n .slice(0, 2)\n .map((part) => part[0]?.toUpperCase())\n .join(\"\");\n\n return initials || \"?\";\n}\n\nfunction PostArticleCta({\n cta,\n}: {\n cta: NonNullable<ArticlePageProps[\"postArticleCta\"]>;\n}) {\n return (\n <div className=\"rounded-2xl border border-[var(--blog-accent-border)] bg-[var(--blog-accent-bg)] p-5 sm:p-6\">\n <div className=\"flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between\">\n <div className=\"space-y-1\">\n <h2 className=\"text-foreground text-xl font-semibold\">{cta.title}</h2>\n {cta.description && (\n <p className=\"text-muted-foreground leading-relaxed\">\n {cta.description}\n </p>\n )}\n </div>\n <Link\n href={cta.href}\n className=\"inline-flex shrink-0 items-center justify-center gap-2 rounded-full bg-[var(--blog-accent)] px-4 py-2 text-sm font-semibold text-white transition-opacity hover:opacity-90\"\n >\n {cta.label}\n <ArrowUpRight className=\"size-4\" aria-hidden=\"true\" />\n </Link>\n </div>\n </div>\n );\n}\n\nfunction ArticleShareLinks({ title, url }: { title: string; url: string }) {\n const encodedTitle = encodeURIComponent(title);\n const encodedUrl = encodeURIComponent(url);\n\n return (\n <div className=\"flex flex-wrap items-center justify-center gap-2 sm:gap-3\">\n <ArticleTopActions title={title} url={url} size=\"sm\" />\n <a\n href={`https://x.com/intent/tweet?text=${encodedTitle}&url=${encodedUrl}`}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n aria-label=\"Share on X\"\n className=\"text-muted-foreground hover:text-foreground border-border inline-flex size-9 items-center justify-center rounded-full border grayscale transition-colors hover:border-[var(--blog-accent-border)] hover:bg-[var(--blog-accent-bg)]\"\n >\n <FaXTwitter className=\"size-4\" aria-hidden=\"true\" />\n </a>\n <a\n href={`https://www.linkedin.com/sharing/share-offsite/?url=${encodedUrl}`}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n aria-label=\"Share on LinkedIn\"\n className=\"text-muted-foreground hover:text-foreground border-border inline-flex size-9 items-center justify-center rounded-full border grayscale transition-colors hover:border-[var(--blog-accent-border)] hover:bg-[var(--blog-accent-bg)]\"\n >\n <FaLinkedinIn className=\"size-4\" aria-hidden=\"true\" />\n </a>\n <a\n href={`mailto:?subject=${encodedTitle}&body=${encodedUrl}`}\n aria-label=\"Share by email\"\n className=\"text-muted-foreground hover:text-foreground border-border inline-flex size-9 items-center justify-center rounded-full border grayscale transition-colors hover:border-[var(--blog-accent-border)] hover:bg-[var(--blog-accent-bg)]\"\n >\n <Mail className=\"size-4\" aria-hidden=\"true\" />\n </a>\n </div>\n );\n}\n\nfunction RelatedArticles({\n articles,\n basePath,\n}: {\n articles: PublishedArticle[];\n basePath: string;\n}) {\n return (\n <section className=\"space-y-4\" aria-labelledby=\"related-articles-title\">\n <h2 id=\"related-articles-title\" className=\"text-xl font-semibold\">\n You might also like\n </h2>\n <div className=\"grid gap-4 md:grid-cols-3\">\n {articles.map((article) => (\n <Link\n key={article.id}\n href={buildBlogPath(basePath, article.slug)}\n className=\"group border-border overflow-hidden rounded-2xl border transition-colors hover:border-[var(--blog-accent-border)] hover:bg-[var(--blog-accent-bg)] hover:no-underline\"\n >\n {article.featuredImage && (\n <ArticleCardImage\n src={article.featuredImage}\n alt={\n article.featuredImageAlt ??\n `Featured image for ${article.title}`\n }\n />\n )}\n <div className=\"p-4\">\n <h3 className=\"text-foreground line-clamp-3 font-semibold transition-colors group-hover:text-[var(--blog-text-accent)]\">\n {article.title}\n </h3>\n {article.excerpt && (\n <p className=\"text-muted-foreground mt-2 line-clamp-3 text-sm leading-relaxed\">\n {article.excerpt}\n </p>\n )}\n </div>\n </Link>\n ))}\n </div>\n </section>\n );\n}\n\nfunction ArticleCardImage({ src, alt }: { src: string; alt: string }) {\n return (\n <div className=\"border-border aspect-[16/9] overflow-hidden border-b bg-[var(--blog-accent-bg)]\">\n <Image\n src={src}\n alt={alt}\n width={480}\n height={270}\n className=\"h-full w-full object-cover transition-transform duration-500 group-hover:scale-105\"\n />\n </div>\n );\n}\n\n/**\n * Generate metadata for the article page for SEO optimization.\n * This function should be used in the Next.js metadata API.\n */\nexport function generateArticleMetadata(\n article: PublishedArticle,\n basePath = \"/blog\",\n) {\n const title = article.meta.title ?? article.title;\n const description = article.meta.description ?? article.excerpt;\n const canonicalUrl =\n article.meta.canonicalUrl ??\n `${article.site.domain}${buildBlogPath(basePath, article.slug)}`;\n const ogImage = article.meta.ogImage ?? article.featuredImage;\n\n return {\n title,\n description,\n keywords: article.meta.keywords.join(\", \"),\n authors: article.author ? [{ name: article.author.name }] : undefined,\n openGraph: {\n title,\n description,\n type: \"article\",\n url: canonicalUrl,\n images: ogImage\n ? [{ url: ogImage, alt: article.featuredImageAlt ?? title }]\n : undefined,\n publishedTime: article.publishedAt,\n modifiedTime: article.updatedAt,\n authors: article.author ? [article.author.name] : undefined,\n siteName: article.site.name,\n },\n twitter: {\n card: \"summary_large_image\",\n title,\n description,\n images: ogImage ? [ogImage] : undefined,\n },\n alternates: {\n canonical: canonicalUrl,\n },\n };\n}\n","import React from \"react\";\nimport Image from \"next/image\";\nimport Link from \"next/link\";\nimport { ArrowLeft, Globe, Mail } from \"lucide-react\";\nimport { formatDistanceToNow } from \"date-fns\";\n\nimport Pagination from \"../../../../components/Pagination\";\nimport { Badge } from \"../../../../components/ui/badge\";\nimport { Separator } from \"../../../../components/ui/separator\";\nimport {\n createStructuredDataScript,\n generateAuthorStructuredData,\n} from \"../../../../lib/structured-data\";\nimport { cn } from \"../../../../lib/utils\";\nimport {\n buildBlogPath,\n buildAuthorPath,\n normalizeBlogBasePath,\n} from \"../../../../lib/urls\";\nimport {\n BLOG_PAGE_TITLE_GRADIENT_CLASS,\n type BlogTheme,\n getBlogThemeStyle,\n} from \"../../../../lib/article-ui\";\nimport type {\n PublishedArticle,\n PublishedAuthor,\n PublishedSite,\n} from \"../../../../types/contracts\";\n\ninterface AuthorPageProps {\n author: PublishedAuthor;\n articles: PublishedArticle[];\n site: PublishedSite;\n className?: string;\n basePath?: string;\n theme?: BlogTheme;\n pagination?: {\n currentPage: number;\n totalPages: number;\n baseUrl?: string;\n totalItems?: number;\n };\n navigation?: {\n backToHome?: {\n url: string;\n label?: string;\n };\n };\n}\n\nexport default function AuthorPage({\n author,\n articles,\n site,\n className,\n basePath = \"/blog\",\n theme,\n pagination,\n navigation,\n}: AuthorPageProps) {\n const normalizedBasePath = normalizeBlogBasePath(basePath) || \"/\";\n const backUrl = navigation?.backToHome?.url ?? normalizedBasePath;\n const authorUrl = buildAuthorPath(normalizedBasePath, author.slug);\n const totalArticleCount = pagination?.totalItems ?? articles.length;\n const structuredDataProps = createStructuredDataScript(\n generateAuthorStructuredData(author, {\n pathPrefix: normalizedBasePath,\n }),\n );\n\n return (\n <main\n style={getBlogThemeStyle(theme)}\n className={cn(\n \"author-page mx-auto max-w-5xl px-4 py-8 sm:px-6 sm:py-12 lg:px-8 lg:py-16\",\n className,\n )}\n >\n <header className=\"mb-10 space-y-8 sm:mb-14\">\n <Link\n href={backUrl}\n className=\"text-muted-foreground group focus-visible:ring-ring inline-flex items-center gap-2 rounded-md px-2 py-1 text-sm font-medium transition-colors hover:text-[var(--blog-accent)] focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-none\"\n >\n <ArrowLeft\n className=\"size-4 transition-transform group-hover:-translate-x-1\"\n aria-hidden=\"true\"\n />\n {navigation?.backToHome?.label ?? \"Back to all articles\"}\n </Link>\n\n <div className=\"grid gap-6 sm:grid-cols-[auto_minmax(0,1fr)] sm:items-center\">\n <AuthorAvatar author={author} />\n <div className=\"min-w-0 space-y-4\">\n <div className=\"space-y-2\">\n <div className=\"flex flex-wrap items-center gap-2\">\n {author.isGuest && (\n <Badge variant=\"outline\" className=\"text-xs\">\n Guest Author\n </Badge>\n )}\n </div>\n <h1\n className={cn(\n \"text-4xl leading-tight font-light text-balance sm:text-5xl\",\n BLOG_PAGE_TITLE_GRADIENT_CLASS,\n )}\n >\n {author.name}\n </h1>\n </div>\n\n {author.bio && (\n <p className=\"text-muted-foreground max-w-3xl text-lg leading-relaxed text-pretty\">\n {author.bio}\n </p>\n )}\n\n <AuthorSocialLinks author={author} />\n </div>\n </div>\n </header>\n\n <Separator className=\"mb-8\" />\n\n <section aria-labelledby=\"author-articles-title\" className=\"space-y-6\">\n <div className=\"flex flex-wrap items-end justify-between gap-3\">\n <div>\n <h2\n id=\"author-articles-title\"\n className=\"text-foreground text-2xl font-semibold\"\n >\n Articles by {author.name}\n </h2>\n <p className=\"text-muted-foreground mt-1 text-sm\">\n {totalArticleCount}{\" \"}\n {totalArticleCount === 1 ? \"article\" : \"articles\"} on {site.name}\n </p>\n </div>\n </div>\n\n {articles.length === 0 ? (\n <p className=\"text-muted-foreground border-border rounded-2xl border p-6\">\n This author does not have any published articles yet.\n </p>\n ) : (\n <div className=\"divide-border divide-y\">\n {articles.map((article) => (\n <AuthorArticlePreview\n key={article.id}\n article={article}\n basePath={normalizedBasePath}\n />\n ))}\n </div>\n )}\n\n {pagination && pagination.totalPages > 1 && (\n <div className=\"pt-4\">\n <Pagination\n currentPage={pagination.currentPage}\n totalPages={pagination.totalPages}\n baseUrl={pagination.baseUrl ?? authorUrl}\n className=\"justify-center\"\n />\n </div>\n )}\n </section>\n\n <script\n type={structuredDataProps.type}\n dangerouslySetInnerHTML={structuredDataProps.dangerouslySetInnerHTML}\n />\n </main>\n );\n}\n\nfunction AuthorSocialLinks({ author }: { author: PublishedAuthor }) {\n const links = getAuthorSocialLinks(author);\n\n if (links.length === 0) {\n return null;\n }\n\n return (\n <div\n className=\"flex flex-wrap items-center gap-2\"\n aria-label=\"Author links\"\n >\n {links.map((link) => (\n <a\n key={link.label}\n href={link.href}\n target={link.external ? \"_blank\" : undefined}\n rel={link.external ? \"noopener noreferrer\" : undefined}\n aria-label={link.ariaLabel}\n className=\"text-muted-foreground hover:text-foreground border-border inline-flex size-9 items-center justify-center rounded-full border grayscale transition-colors hover:border-[var(--blog-accent-border)] hover:bg-[var(--blog-accent-bg)]\"\n >\n {link.icon}\n </a>\n ))}\n </div>\n );\n}\n\nfunction getAuthorSocialLinks(author: PublishedAuthor) {\n const links = author.socialLinks;\n\n if (!links) {\n return [];\n }\n\n return [\n links.website\n ? {\n href: links.website,\n label: \"website\",\n ariaLabel: `${author.name}'s website`,\n external: true,\n icon: <Globe className=\"size-4\" aria-hidden=\"true\" />,\n }\n : null,\n (links.x ?? links.twitter)\n ? {\n href: links.x ?? links.twitter ?? \"\",\n label: \"x\",\n ariaLabel: `${author.name} on X`,\n external: true,\n icon: (\n <span className=\"text-sm font-semibold\" aria-hidden=\"true\">\n X\n </span>\n ),\n }\n : null,\n links.linkedin\n ? {\n href: links.linkedin,\n label: \"linkedin\",\n ariaLabel: `${author.name} on LinkedIn`,\n external: true,\n icon: (\n <span className=\"text-sm font-bold\" aria-hidden=\"true\">\n in\n </span>\n ),\n }\n : null,\n links.github\n ? {\n href: links.github,\n label: \"github\",\n ariaLabel: `${author.name} on GitHub`,\n external: true,\n icon: (\n <span className=\"text-xs font-bold\" aria-hidden=\"true\">\n GH\n </span>\n ),\n }\n : null,\n links.email\n ? {\n href: `mailto:${links.email}`,\n label: \"email\",\n ariaLabel: `Email ${author.name}`,\n external: false,\n icon: <Mail className=\"size-4\" aria-hidden=\"true\" />,\n }\n : null,\n ].filter((link): link is NonNullable<typeof link> => link !== null);\n}\n\nfunction AuthorArticlePreview({\n article,\n basePath,\n}: {\n article: PublishedArticle;\n basePath: string;\n}) {\n const publishedRelativeLabel = formatDistanceToNow(\n new Date(article.publishedAt),\n { addSuffix: true },\n );\n\n return (\n <article className=\"py-6 first:pt-0 last:pb-0\">\n <Link\n href={buildBlogPath(basePath, article.slug)}\n className=\"group grid gap-4 hover:no-underline sm:grid-cols-[minmax(0,1fr)_12rem] sm:items-start\"\n >\n <div className=\"min-w-0 space-y-3\">\n <h3 className=\"text-xl leading-tight font-semibold text-balance transition-colors group-hover:text-[var(--blog-text-accent)]\">\n {article.title}\n </h3>\n {article.excerpt && (\n <p className=\"text-muted-foreground line-clamp-3 leading-relaxed\">\n {article.excerpt}\n </p>\n )}\n <div className=\"text-muted-foreground flex flex-wrap items-center gap-x-3 gap-y-1 text-sm\">\n <time dateTime={article.publishedAt}>{publishedRelativeLabel}</time>\n <span aria-hidden=\"true\">•</span>\n <span>{Math.ceil(article.readingSeconds / 60)} min read</span>\n </div>\n </div>\n\n {article.featuredImage && (\n <div className=\"border-border relative aspect-[16/10] overflow-hidden rounded-xl border bg-[var(--blog-accent-bg)]\">\n <Image\n src={article.featuredImage}\n alt={\n article.featuredImageAlt ??\n `Featured image for ${article.title}`\n }\n width={320}\n height={200}\n className=\"h-full w-full object-cover transition-transform duration-500 group-hover:scale-105\"\n />\n </div>\n )}\n </Link>\n </article>\n );\n}\n\nfunction AuthorAvatar({ author }: { author: PublishedAuthor }) {\n if (author.avatarUrl) {\n return (\n <Image\n src={author.avatarUrl}\n alt={author.name}\n width={128}\n height={128}\n className=\"size-28 rounded-full border border-[var(--blog-accent-border)] object-cover sm:size-32\"\n priority\n />\n );\n }\n\n return (\n <span className=\"bg-muted text-muted-foreground inline-flex size-28 items-center justify-center rounded-full text-3xl font-semibold sm:size-32\">\n {getAuthorInitials(author.name)}\n </span>\n );\n}\n\nfunction getAuthorInitials(name: string): string {\n const initials = name\n .trim()\n .split(/\\s+/)\n .filter(Boolean)\n .slice(0, 2)\n .map((part) => part[0]?.toUpperCase())\n .join(\"\");\n\n return initials || \"?\";\n}\n\nexport function generateAuthorPageMetadata(\n author: PublishedAuthor,\n site: PublishedSite,\n basePath = \"/blog\",\n) {\n const canonicalUrl = `https://${site.domain\n .replace(/^https?:\\/\\//, \"\")\n .replace(/\\/+$/, \"\")}${buildAuthorPath(basePath, author.slug)}`;\n const title = `${author.name} - ${site.name}`;\n const description =\n author.bio ?? `Read articles by ${author.name} on ${site.name}.`;\n\n return {\n title,\n description,\n authors: [{ name: author.name }],\n openGraph: {\n title,\n description,\n type: \"profile\",\n url: canonicalUrl,\n images: author.avatarUrl\n ? [{ url: author.avatarUrl, alt: author.name }]\n : undefined,\n siteName: site.name,\n },\n twitter: {\n card: author.avatarUrl ? \"summary_large_image\" : \"summary\",\n title,\n description,\n images: author.avatarUrl ? [author.avatarUrl] : undefined,\n },\n alternates: {\n canonical: canonicalUrl,\n },\n };\n}\n","/**\n * Database interface for blog platform storage\n *\n * This provides a simple interface for storing published articles\n * without coupling to any specific database implementation.\n * Customers can implement this interface with their preferred database.\n */\n\nimport type { PublishedArticle, PublishResult } from \"@/types/contracts\";\n\nexport interface BlogPlatformStorage {\n /**\n * Store a published article\n */\n saveArticle(\n article: PublishedArticle,\n idempotencyKey: string,\n ): Promise<PublishResult>;\n\n /**\n * Get an article by slug\n */\n getArticle(slug: string): Promise<PublishedArticle | null>;\n\n /**\n * List all published articles\n */\n listArticles(options?: {\n limit?: number;\n offset?: number;\n sortBy?: \"publishedAt\" | \"updatedAt\";\n order?: \"asc\" | \"desc\";\n }): Promise<{\n articles: PublishedArticle[];\n total: number;\n }>;\n\n /**\n * Remove an article by slug\n */\n removeArticle(slug: string, idempotencyKey: string): Promise<PublishResult>;\n\n /**\n * Check if an operation was already performed (idempotency)\n */\n checkIdempotency(idempotencyKey: string): Promise<PublishResult | null>;\n\n /**\n * Store the result of an operation for idempotency\n */\n storeOperationResult(\n idempotencyKey: string,\n result: PublishResult,\n ): Promise<void>;\n}\n\n/**\n * Default in-memory storage implementation for development/testing\n * IMPORTANT: This is not suitable for production use!\n */\nexport class InMemoryStorage implements BlogPlatformStorage {\n private articles = new Map<string, PublishedArticle>();\n private operations = new Map<string, PublishResult>();\n\n async saveArticle(\n article: PublishedArticle,\n idempotencyKey: string,\n ): Promise<PublishResult> {\n // Check for existing idempotency key\n const existingResult = await this.checkIdempotency(idempotencyKey);\n\n // CRITICAL FIX: Allow republish after unpublish\n // If we found a cached operation result AND it was successful,\n // check if the article still exists. If it was removed (unpublished),\n // proceed with the save to allow republishing.\n if (existingResult) {\n if (existingResult.success) {\n // Check if article still exists by finding it in the articles map\n const articleStillExists = Array.from(this.articles.values()).some(\n (a) => a.id === article.id,\n );\n\n // If article was removed, allow republish by not returning cached result\n if (!articleStillExists) {\n // Article was unpublished - proceed with save\n } else {\n // Article still exists - this is a true duplicate\n return existingResult;\n }\n } else {\n // Failed operations are always returned as-is\n return existingResult;\n }\n }\n\n // Validate slug uniqueness\n if (this.articles.has(article.slug)) {\n const result: PublishResult = {\n success: false,\n error: {\n code: \"PUB003\",\n message: \"This URL is already in use. Please choose another.\",\n },\n idempotencyKey,\n };\n await this.storeOperationResult(idempotencyKey, result);\n return result;\n }\n\n // Store the article\n this.articles.set(article.slug, article);\n\n const result: PublishResult = {\n success: true,\n url: `/${article.slug}`,\n platformPostId: article.id,\n publishedAt: article.publishedAt,\n idempotencyKey,\n };\n\n await this.storeOperationResult(idempotencyKey, result);\n return result;\n }\n\n async getArticle(slug: string): Promise<PublishedArticle | null> {\n return this.articles.get(slug) ?? null;\n }\n\n async listArticles(\n options: {\n limit?: number;\n offset?: number;\n sortBy?: \"publishedAt\" | \"updatedAt\";\n order?: \"asc\" | \"desc\";\n } = {},\n ): Promise<{ articles: PublishedArticle[]; total: number }> {\n const {\n limit = 10,\n offset = 0,\n sortBy = \"publishedAt\",\n order = \"desc\",\n } = options;\n\n const allArticles = Array.from(this.articles.values());\n\n // Sort articles\n allArticles.sort((a, b) => {\n const aValue = new Date(a[sortBy]).getTime();\n const bValue = new Date(b[sortBy]).getTime();\n return order === \"desc\" ? bValue - aValue : aValue - bValue;\n });\n\n // Apply pagination\n const articles = allArticles.slice(offset, offset + limit);\n\n return {\n articles,\n total: allArticles.length,\n };\n }\n\n async removeArticle(\n slug: string,\n idempotencyKey: string,\n ): Promise<PublishResult> {\n // Check for existing idempotency key\n const existingResult = await this.checkIdempotency(idempotencyKey);\n\n // CRITICAL FIX: Allow re-unpublish after republish\n // If we found a cached operation result AND it was successful,\n // check if the article NOW exists. If it was republished,\n // proceed with the removal to allow re-unpublishing.\n if (existingResult) {\n if (existingResult.success) {\n // Check if article exists NOW (might have been republished)\n const articleExists = this.articles.has(slug);\n\n // If article EXISTS, it was republished - allow re-unpublish\n if (articleExists) {\n // Article was republished - proceed with removal\n } else {\n // Article still removed - this is a true duplicate\n return existingResult;\n }\n } else {\n // Failed operations are always returned as-is\n return existingResult;\n }\n }\n\n // Check if article exists\n if (!this.articles.has(slug)) {\n const result: PublishResult = {\n success: false,\n error: {\n code: \"PUB007\",\n message: \"Article not found\",\n },\n idempotencyKey,\n };\n await this.storeOperationResult(idempotencyKey, result);\n return result;\n }\n\n // Remove the article\n this.articles.delete(slug);\n\n const result: PublishResult = {\n success: true,\n idempotencyKey,\n };\n\n await this.storeOperationResult(idempotencyKey, result);\n return result;\n }\n\n async checkIdempotency(\n idempotencyKey: string,\n ): Promise<PublishResult | null> {\n return this.operations.get(idempotencyKey) ?? null;\n }\n\n async storeOperationResult(\n idempotencyKey: string,\n result: PublishResult,\n ): Promise<void> {\n this.operations.set(idempotencyKey, result);\n }\n}\n\ntype GlobalWithStorage = typeof globalThis & {\n __BLOG_PLATFORM_STORAGE__?: BlogPlatformStorage;\n __BLOG_PLATFORM_STORAGE_WARNED__?: boolean;\n};\n\nfunction warnAboutEphemeralStorage(): void {\n const globalRef = globalThis as GlobalWithStorage;\n if (globalRef.__BLOG_PLATFORM_STORAGE_WARNED__) {\n return;\n }\n\n globalRef.__BLOG_PLATFORM_STORAGE_WARNED__ = true;\n\n const message =\n \"Blog platform: No storage provider configured. Falling back to in-memory storage (data is not persisted).\";\n if (process.env.NODE_ENV === \"production\") {\n console.error(\n `${message} Call initBlogPlatform({ storage: /* your persistent adapter */ }) to avoid data loss.`,\n );\n } else {\n console.warn(message);\n }\n}\n\nfunction getGlobalStorage(): BlogPlatformStorage {\n const globalRef = globalThis as GlobalWithStorage;\n if (!globalRef.__BLOG_PLATFORM_STORAGE__) {\n warnAboutEphemeralStorage();\n globalRef.__BLOG_PLATFORM_STORAGE__ = new InMemoryStorage();\n }\n const storage = globalRef.__BLOG_PLATFORM_STORAGE__;\n if (!storage) {\n // This should be unreachable because we set it above,\n // but the guard satisfies strict type checking without assertions.\n throw new Error(\"Blog platform storage not initialized\");\n }\n return storage;\n}\n\nexport function getStorage(): BlogPlatformStorage {\n return getGlobalStorage();\n}\n\nexport function setStorage(storage: BlogPlatformStorage): void {\n const globalRef = globalThis as GlobalWithStorage;\n globalRef.__BLOG_PLATFORM_STORAGE__ = storage;\n}\n","import type { BlogPlatformStorage } from \"./database\";\nimport { getStorage } from \"./database\";\nimport type { PublishedArticle, PublishedAuthor } from \"../types/contracts\";\n\nexport interface AuthorArchive {\n author: PublishedAuthor;\n articles: PublishedArticle[];\n}\n\nexport interface AuthorArchiveOptions {\n limit?: number;\n offset?: number;\n}\n\nexport function getAuthorsFromArticles(\n articles: readonly PublishedArticle[],\n): PublishedAuthor[] {\n const authorsBySlug = new Map<string, PublishedAuthor>();\n\n for (const article of articles) {\n if (article.author?.slug) {\n authorsBySlug.set(\n article.author.slug,\n mergeAuthorProfile(\n authorsBySlug.get(article.author.slug),\n article.author,\n ),\n );\n }\n }\n\n return Array.from(authorsBySlug.values()).sort((a, b) =>\n a.name.localeCompare(b.name),\n );\n}\n\nexport function getAuthorArchive(\n slug: string,\n articles: readonly PublishedArticle[],\n): AuthorArchive | null {\n const authorArticles = articles\n .filter((article) => article.author?.slug === slug)\n .sort(\n (a, b) =>\n new Date(b.publishedAt).getTime() - new Date(a.publishedAt).getTime(),\n );\n\n const author = authorArticles.reduce<PublishedAuthor | null>(\n (preferredAuthor, article) =>\n article.author\n ? mergeAuthorProfile(preferredAuthor, article.author)\n : preferredAuthor,\n null,\n );\n\n if (!author) {\n return null;\n }\n\n return {\n author,\n articles: authorArticles,\n };\n}\n\nexport async function loadAuthorArchive(\n slug: string,\n options: AuthorArchiveOptions = {},\n storage: BlogPlatformStorage = getStorage(),\n): Promise<AuthorArchive | null> {\n const { articles } = await storage.listArticles({\n limit: options.limit ?? 1000,\n offset: options.offset ?? 0,\n sortBy: \"publishedAt\",\n order: \"desc\",\n });\n\n return getAuthorArchive(slug, articles);\n}\n\nfunction mergeAuthorProfile(\n current: PublishedAuthor | null | undefined,\n next: PublishedAuthor,\n): PublishedAuthor {\n if (!current) {\n return next;\n }\n\n return {\n ...current,\n bio: current.bio ?? next.bio,\n avatarUrl: current.avatarUrl ?? next.avatarUrl,\n pronouns: current.pronouns ?? next.pronouns,\n socialLinks: current.socialLinks ?? next.socialLinks,\n toneAdjectives:\n current.toneAdjectives.length > 0\n ? current.toneAdjectives\n : next.toneAdjectives,\n };\n}\n","import type { PublishedArticle, PublishedTopic } from \"../types/contracts\";\n\nexport interface TopicArchive {\n topic: PublishedTopic;\n articles: PublishedArticle[];\n}\n\nexport function getArticlePrimaryTopic(\n article: PublishedArticle,\n): PublishedTopic | null {\n const topics = article.topics ?? [];\n return topics.find((topic) => topic.isPrimary) ?? topics[0] ?? null;\n}\n\nexport function getAllTopics(articles: PublishedArticle[]): PublishedTopic[] {\n const topicsBySlug = new Map<string, PublishedTopic>();\n\n for (const article of articles) {\n for (const topic of article.topics ?? []) {\n if (!topicsBySlug.has(topic.slug)) {\n topicsBySlug.set(topic.slug, topic);\n }\n }\n }\n\n return Array.from(topicsBySlug.values()).sort((a, b) =>\n a.name.localeCompare(b.name),\n );\n}\n\nexport function getTopicArchive(\n articles: PublishedArticle[],\n topicSlug: string,\n): TopicArchive | null {\n const matchingArticles = articles.filter((article) =>\n (article.topics ?? []).some((topic) => topic.slug === topicSlug),\n );\n\n if (matchingArticles.length === 0) {\n return null;\n }\n\n const topic =\n matchingArticles\n .flatMap((article) => article.topics ?? [])\n .find((candidate) => candidate.slug === topicSlug) ?? null;\n\n if (!topic) {\n return null;\n }\n\n return {\n topic,\n articles: matchingArticles,\n };\n}\n","import React from \"react\";\nimport Link from \"next/link\";\nimport Image from \"next/image\";\nimport { formatDistanceToNow } from \"date-fns\";\n\nimport type { PublishedArticle, PublishedTopic } from \"../types/contracts\";\nimport type { BlogTheme } from \"../lib/article-ui\";\nimport {\n BLOG_PAGE_TITLE_GRADIENT_CLASS,\n getBlogThemeStyle,\n} from \"../lib/article-ui\";\nimport { buildBlogPath, normalizeBlogBasePath } from \"../lib/urls\";\nimport { cn } from \"../lib/utils\";\nimport { getAllTopics, getTopicArchive } from \"../lib/topics\";\n\ninterface BlogTopicsIndexPageProps {\n articles: PublishedArticle[];\n basePath?: string;\n title?: string;\n description?: string;\n className?: string;\n theme?: BlogTheme;\n}\n\ninterface BlogTopicArchivePageProps {\n articles: PublishedArticle[];\n topicSlug: string;\n basePath?: string;\n className?: string;\n theme?: BlogTheme;\n}\n\nexport function BlogTopicsIndexPage({\n articles,\n basePath = \"/blog\",\n title = \"Topics\",\n description = \"Browse articles by topic.\",\n className,\n theme,\n}: BlogTopicsIndexPageProps) {\n const normalizedBasePath = normalizeBlogBasePath(basePath) || \"/\";\n const topics = getAllTopics(articles);\n\n return (\n <main\n style={getBlogThemeStyle(theme)}\n className={cn(\n \"blog-topics-page container mx-auto max-w-5xl px-4 py-8 sm:px-6 sm:py-12 lg:px-8 lg:py-16\",\n className,\n )}\n >\n <header className=\"mb-10 space-y-3 text-center\">\n <Link\n href={normalizedBasePath}\n className=\"text-muted-foreground hover:text-[var(--blog-accent)] text-sm font-medium transition-colors\"\n >\n Back to all articles\n </Link>\n <h1\n className={cn(\n \"text-4xl font-light tracking-tight text-balance sm:text-5xl\",\n BLOG_PAGE_TITLE_GRADIENT_CLASS,\n )}\n >\n {title}\n </h1>\n <p className=\"text-muted-foreground mx-auto max-w-2xl text-lg text-pretty\">\n {description}\n </p>\n </header>\n\n {topics.length === 0 ? (\n <p className=\"text-muted-foreground rounded-2xl border p-8 text-center\">\n No topics have published articles yet.\n </p>\n ) : (\n <div className=\"grid gap-4 sm:grid-cols-2 lg:grid-cols-3\">\n {topics.map((topic) => {\n const count = articles.filter((article) =>\n (article.topics ?? []).some(\n (articleTopic) => articleTopic.slug === topic.slug,\n ),\n ).length;\n\n return (\n <Link\n key={topic.slug}\n href={buildBlogPath(normalizedBasePath, `topics/${topic.slug}`)}\n className=\"group rounded-2xl border border-[var(--blog-accent-border)] bg-[var(--blog-card-bg)] p-5 transition hover:border-[var(--blog-accent)] hover:no-underline\"\n >\n <h2 className=\"group-hover:text-[var(--blog-accent)] text-xl font-semibold transition-colors\">\n {topic.name}\n </h2>\n {topic.description && (\n <p className=\"text-muted-foreground mt-2 line-clamp-3 text-sm leading-relaxed\">\n {topic.description}\n </p>\n )}\n <p className=\"text-muted-foreground mt-4 text-sm\">\n {count} {count === 1 ? \"article\" : \"articles\"}\n </p>\n </Link>\n );\n })}\n </div>\n )}\n </main>\n );\n}\n\nexport function BlogTopicArchivePage({\n articles,\n topicSlug,\n basePath = \"/blog\",\n className,\n theme,\n}: BlogTopicArchivePageProps) {\n const normalizedBasePath = normalizeBlogBasePath(basePath) || \"/\";\n const archive = getTopicArchive(articles, topicSlug);\n\n return (\n <main\n style={getBlogThemeStyle(theme)}\n className={cn(\n \"blog-topic-archive-page container mx-auto max-w-5xl px-4 py-8 sm:px-6 sm:py-12 lg:px-8 lg:py-16\",\n className,\n )}\n >\n <header className=\"mb-10 space-y-3 text-center\">\n <Link\n href={buildBlogPath(normalizedBasePath, \"topics\")}\n className=\"text-muted-foreground hover:text-[var(--blog-accent)] text-sm font-medium transition-colors\"\n >\n Back to all topics\n </Link>\n <h1\n className={cn(\n \"text-4xl font-light tracking-tight text-balance sm:text-5xl\",\n BLOG_PAGE_TITLE_GRADIENT_CLASS,\n )}\n >\n {archive?.topic.name ?? \"Topic not found\"}\n </h1>\n {archive?.topic.description && (\n <p className=\"text-muted-foreground mx-auto max-w-2xl text-lg text-pretty\">\n {archive.topic.description}\n </p>\n )}\n </header>\n\n {!archive ? (\n <p className=\"text-muted-foreground rounded-2xl border p-8 text-center\">\n No published articles were found for this topic.\n </p>\n ) : (\n <div className=\"grid gap-5 md:grid-cols-2\">\n {archive.articles.map((article) => (\n <TopicArticleCard\n key={article.id}\n article={article}\n topic={archive.topic}\n basePath={normalizedBasePath}\n />\n ))}\n </div>\n )}\n </main>\n );\n}\n\nfunction TopicArticleCard({\n article,\n topic,\n basePath,\n}: {\n article: PublishedArticle;\n topic: PublishedTopic;\n basePath: string;\n}) {\n const articleUrl = buildBlogPath(basePath, article.slug);\n const publishedAgo = formatDistanceToNow(new Date(article.publishedAt), {\n addSuffix: true,\n });\n\n return (\n <Link\n href={articleUrl}\n className=\"group overflow-hidden rounded-2xl border border-[var(--blog-accent-border)] bg-[var(--blog-card-bg)] transition hover:border-[var(--blog-accent)] hover:no-underline\"\n >\n {article.featuredImage && (\n <div className=\"relative aspect-[16/9] overflow-hidden\">\n <Image\n src={article.featuredImage}\n alt={article.featuredImageAlt ?? article.title}\n width={640}\n height={360}\n className=\"h-full w-full object-cover transition-transform duration-300 group-hover:scale-105\"\n />\n </div>\n )}\n <div className=\"space-y-3 p-5\">\n <span className=\"inline-flex rounded-full border border-[var(--blog-accent-border)] px-2.5 py-1 text-xs font-medium text-[var(--blog-text-accent)]\">\n {topic.name}\n </span>\n <h2 className=\"group-hover:text-[var(--blog-accent)] text-xl font-semibold text-balance transition-colors\">\n {article.title}\n </h2>\n {article.excerpt && (\n <p className=\"text-muted-foreground line-clamp-3 text-sm leading-relaxed\">\n {article.excerpt}\n </p>\n )}\n <p className=\"text-muted-foreground text-sm\">{publishedAgo}</p>\n </div>\n </Link>\n );\n}\n","import React from \"react\";\nimport Image from \"next/image\";\nimport Link from \"next/link\";\n\nimport type { PublishedArticle, PublishedAuthor } from \"../types/contracts\";\nimport type { BlogTheme } from \"../lib/article-ui\";\nimport {\n BLOG_PAGE_TITLE_GRADIENT_CLASS,\n getBlogThemeStyle,\n} from \"../lib/article-ui\";\nimport { getAuthorsFromArticles } from \"../lib/authors\";\nimport { buildAuthorPath, normalizeBlogBasePath } from \"../lib/urls\";\nimport { cn } from \"../lib/utils\";\n\ninterface BlogAuthorsIndexPageProps {\n articles: PublishedArticle[];\n basePath?: string;\n title?: string;\n description?: string;\n className?: string;\n theme?: BlogTheme;\n}\n\nexport function BlogAuthorsIndexPage({\n articles,\n basePath = \"/blog\",\n title = \"Authors\",\n description = \"Browse articles by author.\",\n className,\n theme,\n}: BlogAuthorsIndexPageProps) {\n const normalizedBasePath = normalizeBlogBasePath(basePath) || \"/\";\n const authors = getAuthorsFromArticles(articles);\n\n return (\n <main\n style={getBlogThemeStyle(theme)}\n className={cn(\n \"blog-authors-page container mx-auto max-w-5xl px-4 py-8 sm:px-6 sm:py-12 lg:px-8 lg:py-16\",\n className,\n )}\n >\n <header className=\"mb-10 space-y-3 text-center\">\n <Link\n href={normalizedBasePath}\n className=\"text-muted-foreground text-sm font-medium transition-colors hover:text-[var(--blog-accent)]\"\n >\n Back to all articles\n </Link>\n <h1\n className={cn(\n \"text-4xl font-light tracking-tight text-balance sm:text-5xl\",\n BLOG_PAGE_TITLE_GRADIENT_CLASS,\n )}\n >\n {title}\n </h1>\n <p className=\"text-muted-foreground mx-auto max-w-2xl text-lg text-pretty\">\n {description}\n </p>\n </header>\n\n {authors.length === 0 ? (\n <p className=\"text-muted-foreground rounded-2xl border p-8 text-center\">\n No authors have published articles yet.\n </p>\n ) : (\n <div className=\"grid gap-4 sm:grid-cols-2 lg:grid-cols-3\">\n {authors.map((author) => {\n const count = articles.filter(\n (article) => article.author?.slug === author.slug,\n ).length;\n\n return (\n <Link\n key={author.slug}\n href={buildAuthorPath(normalizedBasePath, author.slug)}\n className=\"group rounded-2xl border border-[var(--blog-accent-border)] bg-[var(--blog-card-bg)] p-5 transition hover:border-[var(--blog-accent)] hover:no-underline\"\n >\n <div className=\"flex items-start gap-4\">\n <AuthorAvatar author={author} />\n <div className=\"min-w-0 space-y-2\">\n <h2 className=\"text-xl font-semibold transition-colors group-hover:text-[var(--blog-accent)]\">\n {author.name}\n </h2>\n {author.bio && (\n <p className=\"text-muted-foreground line-clamp-3 text-sm leading-relaxed\">\n {author.bio}\n </p>\n )}\n <p className=\"text-muted-foreground text-sm\">\n {count} {count === 1 ? \"article\" : \"articles\"}\n </p>\n </div>\n </div>\n </Link>\n );\n })}\n </div>\n )}\n </main>\n );\n}\n\nfunction AuthorAvatar({ author }: { author: PublishedAuthor }) {\n const initials = getAuthorInitials(author.name);\n\n if (author.avatarUrl) {\n return (\n <Image\n src={author.avatarUrl}\n alt={author.name}\n width={56}\n height={56}\n className=\"size-14 shrink-0 rounded-full border border-[var(--blog-accent-border)] object-cover\"\n />\n );\n }\n\n return (\n <span className=\"bg-muted text-muted-foreground inline-flex size-14 shrink-0 items-center justify-center rounded-full text-base font-semibold\">\n {initials}\n </span>\n );\n}\n\nfunction getAuthorInitials(name: string): string {\n const initials = name\n .trim()\n .split(/\\s+/)\n .filter(Boolean)\n .slice(0, 2)\n .map((part) => part[0]?.toUpperCase())\n .join(\"\");\n\n return initials || \"?\";\n}\n","import { type NextRequest } from \"next/server\";\nimport { createHash } from \"crypto\";\nimport type { PublishResult } from \"@/types/contracts\";\n\n/**\n * Authentication configuration interface\n * Customers can implement this to customize authentication behavior\n */\nexport interface AuthConfig {\n /**\n * Validate an authentication token\n * @param token - The token to validate\n * @returns Promise that resolves to validation result\n */\n validateToken(token: string): Promise<AuthResult>;\n \n /**\n * Extract token from request\n * @param request - The incoming request\n * @returns The extracted token or null if not found\n */\n extractToken?(request: NextRequest): string | null;\n \n /**\n * Custom error messages for authentication failures\n */\n errorMessages?: {\n missing?: string;\n invalid?: string;\n expired?: string;\n };\n}\n\n/**\n * Authentication result from token validation\n */\nexport interface AuthResult {\n /** Whether the token is valid */\n valid: boolean;\n \n /** Error code if invalid */\n errorCode?: \"missing\" | \"invalid\" | \"expired\";\n \n /** Additional user/context information */\n context?: Record<string, unknown>;\n}\n\nexport function createTokenFingerprint(token: string): string {\n return `sha256:${createHash(\"sha256\").update(token).digest(\"hex\")}`;\n}\n\n/**\n * Default token extraction from Authorization header\n * Supports both \"Bearer <token>\" and \"Token <token>\" formats\n */\nexport function extractTokenFromHeader(request: NextRequest): string | null {\n const authHeader = request.headers.get(\"Authorization\");\n if (!authHeader) {\n return null;\n }\n\n // Support both \"Bearer <token>\" and \"Token <token>\" formats\n const bearerRegex = /^Bearer\\s+(.+)$/i;\n const bearerMatch = bearerRegex.exec(authHeader);\n if (bearerMatch?.[1]) {\n return bearerMatch[1];\n }\n\n const tokenRegex = /^Token\\s+(.+)$/i;\n const tokenMatch = tokenRegex.exec(authHeader);\n if (tokenMatch?.[1]) {\n return tokenMatch[1];\n }\n\n return null;\n}\n\n/**\n * Simple API key based authentication implementation\n * Customers can extend this or provide their own AuthConfig\n */\nexport class ApiKeyAuth implements AuthConfig {\n private validApiKeys: Set<string>;\n \n constructor(apiKeys: string[]) {\n this.validApiKeys = new Set(apiKeys);\n }\n\n async validateToken(token: string): Promise<AuthResult> {\n if (!token?.trim()) {\n return {\n valid: false,\n errorCode: \"missing\",\n };\n }\n\n if (this.validApiKeys.has(token)) {\n return {\n valid: true,\n context: {\n tokenHash: this.hashToken(token),\n },\n };\n }\n\n return {\n valid: false,\n errorCode: \"invalid\",\n };\n }\n\n extractToken = (request: NextRequest): string | null => {\n return extractTokenFromHeader(request);\n };\n\n private hashToken(token: string): string {\n return createTokenFingerprint(token);\n }\n}\n\n/**\n * Environment variable based authentication\n * Reads API keys from environment variables\n */\nexport class EnvAuth extends ApiKeyAuth {\n constructor(envVarName = \"BLOG_PLATFORM_API_KEYS\") {\n let apiKeysEnv = process.env[envVarName];\n\n // Backwards compatibility: fall back to BLOG_AUTH_TOKEN when using default env var\n if (!apiKeysEnv && envVarName === \"BLOG_PLATFORM_API_KEYS\") {\n apiKeysEnv = process.env.BLOG_AUTH_TOKEN;\n }\n\n const apiKeys = apiKeysEnv ? apiKeysEnv.split(\",\").map((key) => key.trim()).filter(Boolean) : [];\n\n if (apiKeys.length === 0) {\n const hint = envVarName === \"BLOG_PLATFORM_API_KEYS\"\n ? \" (set BLOG_PLATFORM_API_KEYS or BLOG_AUTH_TOKEN)\"\n : \"\";\n console.warn(\n `⚠️ No API keys found in environment variable ${envVarName}${hint}. Authentication will fail for all requests.`,\n );\n }\n\n super(apiKeys);\n }\n}\n\n/**\n * No-op authentication for development/testing\n * WARNING: Never use this in production!\n */\nexport class NoAuth implements AuthConfig {\n async validateToken(): Promise<AuthResult> {\n return {\n valid: true,\n context: {\n development: true,\n },\n };\n }\n\n extractToken(): string | null {\n return \"development-mode\";\n }\n}\n\n/**\n * Uninitialized authentication - rejects all requests\n * This is the secure default before initialization\n */\nexport class UninitializedAuth implements AuthConfig {\n private hasWarned = false;\n\n async validateToken(_token: string): Promise<AuthResult> {\n if (!this.hasWarned) {\n console.error(\n \"❌ SECURITY WARNING: Blog platform authentication not initialized! \" +\n \"All requests will be rejected. Call initBlogPlatform() to configure authentication.\"\n );\n this.hasWarned = true;\n }\n\n return {\n valid: false,\n errorCode: \"invalid\",\n };\n }\n\n // Don't override extractToken - use default header extraction\n // Don't override error messages - use defaults so users see\n // \"Invalid authentication credentials\" instead of confusing\n // \"platform not initialized\" messages\n}\n\ndeclare global {\n // Using `var` here intentionally to declare a global on Node's globalThis\n // across module boundaries and hot reloads\n var __BLOG_PLATFORM_AUTH_CONFIG__: AuthConfig | undefined;\n}\n\n/**\n * Global authentication configuration\n * Defaults to UninitializedAuth for security (fail closed)\n * Stored in globalThis to persist across Next.js dev mode hot reloads\n */\nfunction getDefaultAuthConfig(): AuthConfig {\n globalThis.__BLOG_PLATFORM_AUTH_CONFIG__ ??= new UninitializedAuth();\n return globalThis.__BLOG_PLATFORM_AUTH_CONFIG__;\n}\n\n/**\n * Set the authentication configuration\n * Customers should call this in their app initialization\n */\nexport function setAuthConfig(config: AuthConfig): void {\n globalThis.__BLOG_PLATFORM_AUTH_CONFIG__ = config;\n}\n\n/**\n * Get the current authentication configuration\n */\nexport function getAuthConfig(): AuthConfig {\n return globalThis.__BLOG_PLATFORM_AUTH_CONFIG__ ?? getDefaultAuthConfig();\n}\n\n/**\n * Initialize authentication with environment-based API keys\n * This is a convenience function for common setups\n */\nexport function initEnvAuth(envVarName?: string): void {\n setAuthConfig(new EnvAuth(envVarName));\n}\n\n/**\n * Authenticate an incoming request\n * @param request - The Next.js request object\n * @returns Authentication result with token validation\n */\nexport async function authenticateRequest(request: NextRequest): Promise<{\n authenticated: boolean;\n result: AuthResult;\n token: string | null;\n}> {\n const config = getAuthConfig();\n\n // Extract token using configured method or default\n const token = config.extractToken ? config.extractToken(request) : extractTokenFromHeader(request);\n\n if (!token) {\n return {\n authenticated: false,\n result: {\n valid: false,\n errorCode: \"missing\",\n },\n token: null,\n };\n }\n\n // Validate the token\n const result = await config.validateToken(token);\n\n return {\n authenticated: result.valid,\n result,\n token,\n };\n}\n\n/**\n * Create an authentication error response\n * @param authResult - The failed authentication result\n * @param idempotencyKey - Optional idempotency key from request\n * @returns NextResponse with appropriate error\n */\nexport function createAuthErrorResponse(\n authResult: AuthResult,\n idempotencyKey = \"\"\n): PublishResult {\n const config = getAuthConfig();\n const customMessages = config.errorMessages ?? {};\n \n let message: string;\n let code: string;\n \n switch (authResult.errorCode) {\n case \"missing\":\n message = customMessages.missing ?? \"Authentication token is required\";\n code = \"PUB005\";\n break;\n case \"expired\":\n message = customMessages.expired ?? \"Authentication token has expired\";\n code = \"PUB005\";\n break;\n case \"invalid\":\n default:\n message = customMessages.invalid ?? \"Invalid authentication credentials\";\n code = \"PUB005\";\n break;\n }\n\n return {\n success: false,\n error: {\n code,\n message,\n details: {\n authError: authResult.errorCode ?? \"invalid\",\n },\n },\n idempotencyKey,\n };\n}\n\n/**\n * Middleware function to protect API endpoints\n * Usage in route handlers:\n * \n * ```typescript\n * export async function POST(request: NextRequest) {\n * const authCheck = await requireAuth(request);\n * if (!authCheck.authenticated) {\n * return NextResponse.json(authCheck.error, { status: 401 });\n * }\n * \n * // Continue with authenticated request...\n * }\n * ```\n */\nexport async function requireAuth(request: NextRequest): Promise<{\n authenticated: boolean;\n error?: PublishResult;\n context?: Record<string, unknown>;\n}> {\n const auth = await authenticateRequest(request);\n \n if (!auth.authenticated) {\n return {\n authenticated: false,\n error: createAuthErrorResponse(auth.result),\n };\n }\n\n return {\n authenticated: true,\n context: auth.result.context,\n };\n}\n\n/**\n * Utility to check if current environment should skip authentication\n * Useful for development and testing\n */\nexport function shouldSkipAuth(): boolean {\n const skipAuth = process.env.SKIP_BLOG_PLATFORM_AUTH;\n return skipAuth === \"true\" || skipAuth === \"1\" || process.env.NODE_ENV === \"test\";\n}\n","/**\n * Rate limiting for blog platform API endpoints\n * \n * This implements rate limiting using Upstash Redis to prevent abuse\n * and ensure fair usage across all API consumers.\n */\n\nimport { Ratelimit } from \"@upstash/ratelimit\";\nimport { Redis } from \"@upstash/redis\";\nimport type { PublishResult } from \"@/types/contracts\";\n\n/**\n * Rate limit configuration interface\n * Allows customers to customize rate limiting behavior\n */\nexport interface RateLimitConfig {\n /** Upstash Redis REST URL */\n redisUrl: string;\n \n /** Upstash Redis REST token */\n redisToken: string;\n \n /** Requests per minute limit (default: 5) */\n requestsPerMinute?: number;\n \n /** Redis key prefix for rate limiting (default: \"blog-platform-ratelimit\") */\n keyPrefix?: string;\n \n /** Enable analytics (default: true) */\n analytics?: boolean;\n}\n\n/**\n * Rate limit result\n */\nexport interface RateLimitResult {\n /** Whether the request is allowed */\n success: boolean;\n \n /** Number of requests remaining in current window */\n remaining: number;\n \n /** When the rate limit window resets (Unix timestamp) */\n reset: number;\n \n /** Total requests allowed per window */\n limit: number;\n \n /** Current request count in window */\n count: number;\n}\n\n/**\n * Rate limiter instance\n */\ntype GlobalWithRateLimiter = typeof globalThis & {\n __BLOG_PLATFORM_RATE_LIMITER__?: Ratelimit | null;\n};\n\nfunction getRateLimiter(): Ratelimit | null {\n const globalRef = globalThis as GlobalWithRateLimiter;\n return globalRef.__BLOG_PLATFORM_RATE_LIMITER__ ?? null;\n}\n\nfunction setRateLimiter(instance: Ratelimit | null): void {\n const globalRef = globalThis as GlobalWithRateLimiter;\n globalRef.__BLOG_PLATFORM_RATE_LIMITER__ = instance;\n}\n\n/**\n * Configure the rate limiter\n * This must be called during app initialization\n */\nexport function configureRateLimit(config: RateLimitConfig): void {\n const {\n redisUrl,\n redisToken,\n requestsPerMinute = 5,\n keyPrefix = \"blog-platform-ratelimit\",\n analytics = true,\n } = config;\n\n const redis = new Redis({\n url: redisUrl,\n token: redisToken,\n });\n\n const limiter = new Ratelimit({\n redis,\n analytics,\n prefix: keyPrefix,\n // 5 requests per minute sliding window\n limiter: Ratelimit.slidingWindow(requestsPerMinute, \"1m\"),\n });\n\n setRateLimiter(limiter);\n}\n\n/**\n * Auto-configure rate limiting from environment variables\n * Uses UPSTASH_REDIS_REST_URL and UPSTASH_REDIS_REST_TOKEN\n */\nexport function autoConfigureRateLimit(): void {\n const redisUrl = process.env.UPSTASH_REDIS_REST_URL;\n const redisToken = process.env.UPSTASH_REDIS_REST_TOKEN;\n \n if (!redisUrl || !redisToken) {\n console.warn(\"Blog platform: No Upstash Redis configuration found. Rate limiting disabled.\");\n return;\n }\n \n configureRateLimit({\n redisUrl,\n redisToken,\n });\n \n console.log(\"Blog platform: Rate limiting configured (5 requests per minute per token)\");\n}\n\n/**\n * Check rate limit for a given identifier (typically an auth token)\n * @param identifier - Unique identifier (usually the authentication token)\n * @returns Rate limit result\n */\nexport async function checkRateLimit(identifier: string): Promise<RateLimitResult> {\n const limiter = getRateLimiter();\n if (!limiter) {\n // Rate limiting not configured - allow all requests\n console.warn(\"Blog platform: Rate limiter not configured. All requests allowed.\");\n return {\n success: true,\n remaining: 999,\n reset: Date.now() + 60000,\n limit: 5,\n count: 0,\n };\n }\n\n try {\n const result = await limiter.limit(identifier);\n \n return {\n success: result.success,\n remaining: result.remaining,\n reset: result.reset,\n limit: result.limit,\n count: result.limit - result.remaining,\n };\n } catch (error) {\n console.error(\"Blog platform: Rate limit check failed:\", error);\n // On error, allow the request but log the issue\n return {\n success: true,\n remaining: 0,\n reset: Date.now() + 60000,\n limit: 5,\n count: 0,\n };\n }\n}\n\n/**\n * Create a rate limit error response\n * @param rateLimitResult - The rate limit result that failed\n * @param idempotencyKey - Optional idempotency key from request\n * @returns PublishResult with rate limit error\n */\nexport function createRateLimitErrorResponse(\n rateLimitResult: RateLimitResult,\n idempotencyKey = \"\"\n): PublishResult {\n const resetMinutes = Math.ceil((rateLimitResult.reset - Date.now()) / 60000);\n \n return {\n success: false,\n error: {\n code: \"PUB011\",\n message: `Rate limit exceeded. You can make ${rateLimitResult.limit} requests per minute. Try again in ${resetMinutes} minute(s).`,\n details: {\n rateLimit: rateLimitResult,\n },\n },\n idempotencyKey,\n };\n}\n\n/**\n * Rate limiting middleware for API routes\n * @param identifier - Unique identifier for rate limiting (typically auth token)\n * @param idempotencyKey - Optional idempotency key from request\n * @returns Rate limit result or error response\n */\nexport async function enforceRateLimit(\n identifier: string,\n idempotencyKey = \"\"\n): Promise<{ allowed: true; rateLimitResult: RateLimitResult } | { allowed: false; errorResponse: PublishResult }> {\n const rateLimitResult = await checkRateLimit(identifier);\n \n if (!rateLimitResult.success) {\n return {\n allowed: false,\n errorResponse: createRateLimitErrorResponse(rateLimitResult, idempotencyKey),\n };\n }\n \n return {\n allowed: true,\n rateLimitResult,\n };\n}\n\n/**\n * Get rate limit headers for HTTP responses\n * @param rateLimitResult - Rate limit result\n * @returns Headers object for HTTP response\n */\nexport function getRateLimitHeaders(rateLimitResult: RateLimitResult): Record<string, string> {\n return {\n \"X-RateLimit-Limit\": rateLimitResult.limit.toString(),\n \"X-RateLimit-Remaining\": rateLimitResult.remaining.toString(),\n \"X-RateLimit-Reset\": rateLimitResult.reset.toString(),\n \"Retry-After\": Math.ceil((rateLimitResult.reset - Date.now()) / 1000).toString(),\n };\n}\n","/**\n * Initialization utilities for the blog platform package\n *\n * This module provides convenient setup functions for customers\n * to configure authentication, storage, and other platform features.\n */\n\nimport {\n setAuthConfig,\n type AuthConfig,\n NoAuth,\n EnvAuth,\n} from \"./auth\";\nimport { setStorage, type BlogPlatformStorage } from \"./database\";\nimport {\n autoConfigureRateLimit,\n configureRateLimit,\n type RateLimitConfig,\n} from \"./ratelimit\";\n\ndeclare global {\n // Using `var` here intentionally to declare a global on Node's globalThis\n // across module boundaries. This is not a directive; remove stale disable.\n var __BLOG_PLATFORM_INITIALISED__: boolean | undefined;\n}\n\n/**\n * Configuration options for blog platform initialization\n */\nexport interface BlogPlatformConfig {\n /** Authentication configuration (REQUIRED) */\n auth: AuthConfig;\n\n /** Custom storage implementation */\n storage?: BlogPlatformStorage;\n\n /** Custom rate limiting configuration */\n rateLimit?: RateLimitConfig;\n\n /** Whether to automatically configure rate limiting from environment */\n autoRateLimit?: boolean;\n}\n\n/**\n * Initialize the blog platform with custom configuration\n *\n * This should be called once during your app startup, typically in:\n * - Next.js: middleware.ts or layout.tsx\n * - Express: app startup\n * - Other frameworks: main entry point\n *\n * @param config - Configuration options (auth is REQUIRED)\n *\n * @example\n * ```typescript\n * // Environment-based API key authentication\n * initBlogPlatform({\n * auth: new EnvAuth(), // Reads from BLOG_PLATFORM_API_KEYS\n * });\n *\n * // Custom environment variable\n * initBlogPlatform({\n * auth: new EnvAuth(\"MY_BLOG_API_KEYS\"),\n * });\n *\n * // Custom authentication provider\n * initBlogPlatform({\n * auth: new CustomAuthProvider(),\n * storage: new PostgresStorage(connectionString),\n * rateLimit: {\n * redisUrl: \"https://...\",\n * redisToken: \"...\",\n * requestsPerMinute: 10\n * }\n * });\n *\n * // Disable rate limiting for testing\n * initBlogPlatform({\n * auth: new NoAuth(), // Development only!\n * autoRateLimit: false\n * });\n * ```\n */\nexport function initBlogPlatform(config: BlogPlatformConfig): void {\n const {\n auth,\n storage,\n rateLimit,\n autoRateLimit = true,\n } = config;\n\n // Validate required configuration\n if (!auth) {\n throw new Error(\n \"Blog platform initialization failed: 'auth' is required.\\n\" +\n \"Example: initBlogPlatform({ auth: new EnvAuth() })\\n\" +\n \"See https://github.com/xexr/blog-platform#authentication for more details.\"\n );\n }\n\n // Set up authentication (REQUIRED)\n console.log(\"Blog platform: Setting up authentication\");\n setAuthConfig(auth);\n\n // Set up rate limiting\n if (rateLimit) {\n console.log(\"Blog platform: Using custom rate limiting configuration\");\n configureRateLimit(rateLimit);\n } else if (autoRateLimit) {\n console.log(\n \"Blog platform: Auto-configuring rate limiting from environment\",\n );\n autoConfigureRateLimit();\n } else {\n console.log(\"Blog platform: Rate limiting disabled\");\n }\n\n // Set up storage\n if (storage) {\n console.log(\"Blog platform: Using custom storage provider\");\n setStorage(storage);\n } else {\n console.log(\n \"Blog platform: Using default in-memory storage (not suitable for production)\",\n );\n }\n\n console.log(\"Blog platform initialized successfully\");\n globalThis.__BLOG_PLATFORM_INITIALISED__ = true;\n}\n\n/**\n * Initialize the blog platform only once per process.\n * Safe to call from multiple modules (e.g., layout + API routes).\n *\n * @param config - Configuration options (auth is REQUIRED)\n */\nexport function initBlogPlatformOnce(config: BlogPlatformConfig): void {\n if (globalThis.__BLOG_PLATFORM_INITIALISED__) {\n console.log(\"Blog platform: Already initialized, skipping\");\n return;\n }\n console.log(\"Blog platform: Initializing blog platform once\");\n initBlogPlatform(config);\n}\n\n/**\n * Quick setup for development/testing\n * WARNING: Disables authentication - never use in production!\n * Uses NoAuth (accepts all requests), in-memory storage, and disables rate limiting\n */\nexport function initBlogPlatformDev(): void {\n initBlogPlatform({\n auth: new NoAuth(),\n autoRateLimit: false\n });\n console.log(\n \"Blog platform: Development mode enabled (no auth, in-memory storage, no rate limiting)\",\n );\n}\n\n/**\n * Production setup with environment-based API keys and rate limiting\n * Requires BLOG_PLATFORM_API_KEYS (or custom env var), UPSTASH_REDIS_REST_URL,\n * and UPSTASH_REDIS_REST_TOKEN environment variables\n *\n * @param apiKeysEnvVar - Optional custom environment variable name for API keys (default: BLOG_PLATFORM_API_KEYS)\n */\nexport function initBlogPlatformProd(apiKeysEnvVar?: string): void {\n const envVar = apiKeysEnvVar ?? \"BLOG_PLATFORM_API_KEYS\";\n\n if (!process.env[envVar]) {\n throw new Error(\n `Missing required environment variable: ${envVar}. ` +\n \"Set this to a comma-separated list of API keys for blog platform authentication.\",\n );\n }\n\n initBlogPlatform({\n auth: new EnvAuth(envVar),\n autoRateLimit: true,\n });\n console.log(\n \"Blog platform: Production mode enabled (environment-based auth, rate limiting)\",\n );\n}\n","import type { InferSelectModel } from \"drizzle-orm\";\nimport { and, desc, eq, sql } from \"drizzle-orm\";\nimport type { LibSQLDatabase } from \"drizzle-orm/libsql\";\nimport {\n sqliteTable,\n integer,\n text,\n uniqueIndex,\n} from \"drizzle-orm/sqlite-core\";\nimport type {\n PublishedArticle,\n PublishResult,\n PublishedAuthor,\n PublishedSite,\n} from \"../../types/contracts\";\nimport type { BlogPlatformStorage } from \"../database\";\n\n// Schema definitions for durable storage\nexport const bpArticles = sqliteTable(\n \"bp_articles\",\n {\n id: text(\"id\").primaryKey(),\n slug: text(\"slug\").notNull(),\n title: text(\"title\").notNull(),\n excerpt: text(\"excerpt\").notNull(),\n content: text(\"content\").notNull(),\n readingSeconds: integer(\"reading_seconds\").notNull(),\n wordCount: integer(\"word_count\").notNull(),\n publishedAt: text(\"published_at\").notNull(),\n updatedAt: text(\"updated_at\").notNull(),\n featuredImage: text(\"featured_image\"),\n featuredImageAlt: text(\"featured_image_alt\"),\n featuredImageCaption: text(\"featured_image_caption\"),\n featuredImageCreditText: text(\"featured_image_credit_text\"),\n featuredImageCreditUrl: text(\"featured_image_credit_url\"),\n // Store complex objects as JSON strings\n authorJson: text(\"author_json\"),\n siteJson: text(\"site_json\").notNull(),\n metaJson: text(\"meta_json\").notNull(),\n version: integer(\"version\").notNull(),\n },\n (table) => ({\n slugUniqueIdx: uniqueIndex(\"bp_articles_slug_unique\").on(table.slug),\n }),\n);\n\nexport const bpOperations = sqliteTable(\"bp_operations\", {\n key: text(\"key\").primaryKey(),\n // JSON-encoded PublishResult\n resultJson: text(\"result_json\").notNull(),\n createdAt: integer(\"created_at\", { mode: \"timestamp_ms\" }).notNull(),\n // Optional TTL field (not currently used by adapter logic)\n expiresAt: integer(\"expires_at\", { mode: \"timestamp_ms\" }),\n});\n\ntype ArticleRow = InferSelectModel<typeof bpArticles>;\n\nfunction toRow(article: PublishedArticle): ArticleRow {\n return {\n id: article.id,\n slug: article.slug,\n title: article.title,\n excerpt: article.excerpt,\n content: article.content,\n readingSeconds: article.readingSeconds,\n wordCount: article.wordCount,\n publishedAt: article.publishedAt,\n updatedAt: article.updatedAt,\n featuredImage: article.featuredImage ?? null,\n featuredImageAlt: article.featuredImageAlt ?? null,\n featuredImageCaption: article.featuredImageCaption ?? null,\n featuredImageCreditText: article.featuredImageCreditText ?? null,\n featuredImageCreditUrl: article.featuredImageCreditUrl ?? null,\n authorJson: article.author ? JSON.stringify(article.author) : null,\n siteJson: JSON.stringify(article.site),\n metaJson: JSON.stringify({\n ...article.meta,\n __bloggyTopics: article.topics ?? [],\n }),\n version: article.version,\n };\n}\n\nfunction fromRow(row: ArticleRow): PublishedArticle {\n return {\n id: row.id,\n slug: row.slug,\n title: row.title,\n excerpt: row.excerpt,\n content: row.content,\n readingSeconds: row.readingSeconds,\n wordCount: row.wordCount,\n publishedAt: row.publishedAt,\n updatedAt: row.updatedAt,\n featuredImage: row.featuredImage ?? undefined,\n featuredImageAlt: row.featuredImageAlt ?? undefined,\n featuredImageCaption: row.featuredImageCaption ?? undefined,\n featuredImageCreditText: row.featuredImageCreditText ?? undefined,\n featuredImageCreditUrl: row.featuredImageCreditUrl ?? undefined,\n author: row.authorJson\n ? (JSON.parse(row.authorJson) as PublishedAuthor)\n : null,\n site: JSON.parse(row.siteJson) as PublishedSite,\n topics: extractTopics(row.metaJson),\n meta: extractMeta(row.metaJson),\n version: row.version,\n };\n}\n\nfunction extractTopics(metaJson: string): PublishedArticle[\"topics\"] {\n const parsed = JSON.parse(metaJson) as PublishedArticle[\"meta\"] & {\n __bloggyTopics?: PublishedArticle[\"topics\"];\n };\n return parsed.__bloggyTopics ?? [];\n}\n\nfunction extractMeta(metaJson: string): PublishedArticle[\"meta\"] {\n const parsed = JSON.parse(metaJson) as PublishedArticle[\"meta\"] & {\n __bloggyTopics?: PublishedArticle[\"topics\"];\n };\n delete parsed.__bloggyTopics;\n const meta = parsed;\n return meta;\n}\n\nexport interface DrizzleStorageOptions {\n // Optional: limit retention for operations table (ms)\n operationTtlMs?: number;\n}\n\n/**\n * Drizzle-backed durable storage adapter.\n * Pass a Drizzle Database instance created with drizzle-orm/libsql.\n */\nexport class DrizzleStorage implements BlogPlatformStorage {\n private readonly db: LibSQLDatabase;\n private readonly options: DrizzleStorageOptions;\n\n constructor(db: LibSQLDatabase, options: DrizzleStorageOptions = {}) {\n this.db = db;\n this.options = options;\n }\n\n async saveArticle(\n article: PublishedArticle,\n idempotencyKey: string,\n ): Promise<PublishResult> {\n const existing = await this.checkIdempotency(idempotencyKey);\n\n // CRITICAL FIX: Allow republish after unpublish\n // If we found a cached operation result AND it was successful,\n // check if the article still exists. If it was removed (unpublished),\n // proceed with the save to allow republishing.\n if (existing) {\n if (existing.success) {\n // Check if article still exists in database\n const articleExists = await this.db\n .select({ id: bpArticles.id })\n .from(bpArticles)\n .where(eq(bpArticles.id, article.id))\n .limit(1);\n\n // If article was removed, allow republish by not returning cached result\n if (articleExists.length === 0) {\n // Article was unpublished - proceed with save\n } else {\n // Article still exists - this is a true duplicate\n return existing;\n }\n } else {\n // Failed operations are always returned as-is\n return existing;\n }\n }\n\n // Enforce slug uniqueness: if slug exists with a different article id → conflict\n const bySlug = await this.db\n .select()\n .from(bpArticles)\n .where(eq(bpArticles.slug, article.slug))\n .limit(1);\n\n const existingRow = bySlug[0];\n if (existingRow && existingRow.id !== article.id) {\n const conflict: PublishResult = {\n success: false,\n error: {\n code: \"PUB003\",\n message: \"This URL is already in use. Please choose another.\",\n },\n idempotencyKey,\n };\n await this.storeOperationResult(idempotencyKey, conflict);\n return conflict;\n }\n\n // Upsert by id; slug is immutable once set for a given id\n const row = toRow(article);\n\n if (bySlug.length === 0) {\n // Insert new\n await this.db.insert(bpArticles).values(row).run();\n } else {\n // Update existing row for same article id\n await this.db\n .update(bpArticles)\n .set({\n title: row.title,\n excerpt: row.excerpt,\n content: row.content,\n readingSeconds: row.readingSeconds,\n wordCount: row.wordCount,\n updatedAt: row.updatedAt,\n featuredImage: row.featuredImage,\n featuredImageAlt: row.featuredImageAlt,\n featuredImageCaption: row.featuredImageCaption,\n featuredImageCreditText: row.featuredImageCreditText,\n featuredImageCreditUrl: row.featuredImageCreditUrl,\n authorJson: row.authorJson,\n siteJson: row.siteJson,\n metaJson: row.metaJson,\n version: row.version,\n })\n .where(and(eq(bpArticles.id, row.id), eq(bpArticles.slug, row.slug)))\n .run();\n }\n\n const success: PublishResult = {\n success: true,\n url: `/${article.slug}`,\n platformPostId: article.id,\n publishedAt: article.publishedAt,\n idempotencyKey,\n };\n\n await this.storeOperationResult(idempotencyKey, success);\n return success;\n }\n\n async getArticle(slug: string): Promise<PublishedArticle | null> {\n const rows = await this.db\n .select()\n .from(bpArticles)\n .where(eq(bpArticles.slug, slug))\n .limit(1);\n if (!rows[0]) return null;\n return fromRow(rows[0]);\n }\n\n async listArticles(\n options: {\n limit?: number;\n offset?: number;\n sortBy?: \"publishedAt\" | \"updatedAt\";\n order?: \"asc\" | \"desc\";\n } = {},\n ): Promise<{ articles: PublishedArticle[]; total: number }> {\n const {\n limit = 10,\n offset = 0,\n sortBy = \"publishedAt\",\n order = \"desc\",\n } = options;\n const orderColumn =\n sortBy === \"publishedAt\" ? bpArticles.publishedAt : bpArticles.updatedAt;\n const orderBy = order === \"desc\" ? desc(orderColumn) : orderColumn;\n\n const items = await this.db\n .select()\n .from(bpArticles)\n .orderBy(orderBy)\n .limit(limit)\n .offset(offset);\n\n // Total count (approx via window-free query)\n const totalRow = await this.db\n .select({ c: sql<number>`count(*)` })\n .from(bpArticles);\n const total = Number(totalRow?.[0]?.c ?? 0);\n\n return { articles: items.map(fromRow), total };\n }\n\n async removeArticle(\n slug: string,\n idempotencyKey: string,\n ): Promise<PublishResult> {\n const existing = await this.checkIdempotency(idempotencyKey);\n\n // CRITICAL FIX: Allow re-unpublish after republish\n // If we found a cached operation result AND it was successful,\n // check if the article NOW exists. If it was republished,\n // proceed with the removal to allow re-unpublishing.\n if (existing) {\n if (existing.success) {\n // Check if article exists NOW (might have been republished)\n const articleExists = await this.db\n .select({ id: bpArticles.id })\n .from(bpArticles)\n .where(eq(bpArticles.slug, slug))\n .limit(1);\n\n // If article EXISTS, it was republished - allow re-unpublish\n if (articleExists.length > 0) {\n // Article was republished - proceed with removal\n } else {\n // Article still removed - this is a true duplicate\n return existing;\n }\n } else {\n // Failed operations are always returned as-is\n return existing;\n }\n }\n\n const found = await this.db\n .select()\n .from(bpArticles)\n .where(eq(bpArticles.slug, slug))\n .limit(1);\n if (!found[0]) {\n const notFound: PublishResult = {\n success: false,\n error: { code: \"PUB007\", message: \"Article not found\" },\n idempotencyKey,\n };\n await this.storeOperationResult(idempotencyKey, notFound);\n return notFound;\n }\n\n await this.db.delete(bpArticles).where(eq(bpArticles.slug, slug)).run();\n\n const result: PublishResult = { success: true, idempotencyKey };\n await this.storeOperationResult(idempotencyKey, result);\n return result;\n }\n\n async checkIdempotency(\n idempotencyKey: string,\n ): Promise<PublishResult | null> {\n const rows = await this.db\n .select()\n .from(bpOperations)\n .where(eq(bpOperations.key, idempotencyKey))\n .limit(1);\n if (!rows[0]) return null;\n try {\n return JSON.parse(rows[0].resultJson) as PublishResult;\n } catch {\n return null;\n }\n }\n\n async storeOperationResult(\n idempotencyKey: string,\n result: PublishResult,\n ): Promise<void> {\n const now = Date.now();\n const expiresAt = this.options.operationTtlMs\n ? now + this.options.operationTtlMs\n : null;\n // Upsert behavior using ON CONFLICT is not portable via builder; rely on delete+insert\n await this.db\n .delete(bpOperations)\n .where(eq(bpOperations.key, idempotencyKey))\n .run();\n await this.db\n .insert(bpOperations)\n .values({\n key: idempotencyKey,\n resultJson: JSON.stringify(result),\n createdAt: new Date(now),\n expiresAt: expiresAt ? new Date(expiresAt) : null,\n })\n .run();\n }\n}\n\n/**\n * Helper: Return SQL strings for creating required tables.\n * Consumers can embed these in their migrations.\n */\nexport function getDrizzleAdapterSql(): {\n createArticles: string;\n createOperations: string;\n} {\n return {\n createArticles: `CREATE TABLE IF NOT EXISTS bp_articles (\n id TEXT PRIMARY KEY,\n slug TEXT NOT NULL UNIQUE,\n title TEXT NOT NULL,\n excerpt TEXT NOT NULL,\n content TEXT NOT NULL,\n reading_seconds INTEGER NOT NULL,\n word_count INTEGER NOT NULL,\n published_at TEXT NOT NULL,\n updated_at TEXT NOT NULL,\n featured_image TEXT,\n featured_image_alt TEXT,\n featured_image_caption TEXT,\n featured_image_credit_text TEXT,\n featured_image_credit_url TEXT,\n author_json TEXT,\n site_json TEXT NOT NULL,\n meta_json TEXT NOT NULL,\n version INTEGER NOT NULL\n);`,\n createOperations: `CREATE TABLE IF NOT EXISTS bp_operations (\n key TEXT PRIMARY KEY,\n result_json TEXT NOT NULL,\n created_at INTEGER NOT NULL,\n expires_at INTEGER\n);`,\n };\n}\n","/**\n * SEO utilities for canonical URL generation and validation.\n *\n * These utilities ensure proper canonical URL structure for SEO optimization,\n * preventing duplicate content issues and improving search engine indexing.\n */\n\nimport type { PublishedArticle, PublishedSite } from '../types/contracts';\n\n/**\n * Configuration options for canonical URL generation.\n */\nexport interface CanonicalUrlOptions {\n /** Whether to force HTTPS protocol (default: true) */\n forceHttps?: boolean;\n\n /** Whether to remove trailing slashes (default: true) */\n removeTrailingSlash?: boolean;\n\n /** Custom domain override (uses site.domain if not provided) */\n domain?: string;\n\n /** Custom path prefix (default: '/blog') */\n pathPrefix?: string;\n}\n\n/**\n * Normalizes a domain by ensuring proper protocol and removing trailing slashes.\n *\n * @param domain - The domain to normalize\n * @param forceHttps - Whether to force HTTPS protocol\n * @returns The normalized domain\n *\n * @example\n * ```typescript\n * normalizeDomain('example.com') // 'https://example.com'\n * normalizeDomain('http://example.com/') // 'https://example.com'\n * normalizeDomain('https://example.com', false) // 'https://example.com'\n * ```\n */\nexport function normalizeDomain(domain: string, forceHttps = true): string {\n let normalized = domain.trim();\n\n // Remove trailing slashes\n normalized = normalized.replace(/\\/+$/, '');\n\n // Add protocol if missing\n if (!/^https?:\\/\\//.exec(normalized)) {\n normalized = `${forceHttps ? 'https' : 'http'}://${normalized}`;\n }\n\n // Force HTTPS if requested\n if (forceHttps && normalized.startsWith('http://')) {\n normalized = normalized.replace('http://', 'https://');\n }\n\n return normalized;\n}\n\n/**\n * Validates and normalizes a slug for URL usage.\n *\n * @param slug - The slug to validate and normalize\n * @returns The normalized slug\n * @throws Error if slug is invalid\n *\n * @example\n * ```typescript\n * normalizeSlug('hello-world') // 'hello-world'\n * normalizeSlug('Hello World!') // throws Error\n * normalizeSlug('hello--world') // 'hello-world'\n * ```\n */\nexport function normalizeSlug(slug: string): string {\n const trimmed = slug.trim();\n\n if (!trimmed) {\n throw new Error('Slug cannot be empty');\n }\n\n // Check if slug contains only valid characters\n if (!/^[a-z0-9-]+$/.test(trimmed)) {\n throw new Error('Slug can only contain lowercase letters, numbers, and hyphens');\n }\n\n // Remove multiple consecutive hyphens\n const normalized = trimmed.replace(/-+/g, '-');\n\n // Remove leading/trailing hyphens\n const clean = normalized.replace(/^-+|-+$/g, '');\n\n if (!clean) {\n throw new Error('Slug cannot consist only of hyphens');\n }\n\n return clean;\n}\n\n/**\n * Generates a canonical URL for an article.\n *\n * @param article - The published article\n * @param options - Configuration options for URL generation\n * @returns The canonical URL\n * @throws Error if article or site data is invalid\n *\n * @example\n * ```typescript\n * const article = {\n * slug: 'hello-world',\n * site: { domain: 'example.com' },\n * // ... other fields\n * };\n *\n * generateCanonicalUrl(article)\n * // 'https://example.com/blog/hello-world'\n *\n * generateCanonicalUrl(article, { pathPrefix: '/posts' })\n * // 'https://example.com/posts/hello-world'\n * ```\n */\nexport function generateCanonicalUrl(\n article: PublishedArticle,\n options: CanonicalUrlOptions = {}\n): string {\n const {\n forceHttps = true,\n removeTrailingSlash = true,\n domain = article.site.domain,\n pathPrefix = '/blog'\n } = options;\n\n if (!domain) {\n throw new Error('Domain is required for canonical URL generation');\n }\n\n if (!article.slug) {\n throw new Error('Article slug is required for canonical URL generation');\n }\n\n // Validate and normalize inputs\n const normalizedDomain = normalizeDomain(domain, forceHttps);\n const normalizedSlug = normalizeSlug(article.slug);\n\n // Ensure path prefix starts with '/' and doesn't end with '/'\n const cleanPrefix = pathPrefix\n .replace(/^(?!\\/)/, '/') // Add leading slash if missing\n .replace(/\\/+$/, ''); // Remove trailing slashes\n\n // Construct the canonical URL\n let canonicalUrl = `${normalizedDomain}${cleanPrefix}/${normalizedSlug}`;\n\n // Remove trailing slash if requested\n if (removeTrailingSlash) {\n canonicalUrl = canonicalUrl.replace(/\\/+$/, '');\n }\n\n return canonicalUrl;\n}\n\n/**\n * Generates a canonical URL for an article from site and slug data.\n * Useful when you don't have a full PublishedArticle object.\n *\n * @param site - The published site\n * @param slug - The article slug\n * @param options - Configuration options for URL generation\n * @returns The canonical URL\n *\n * @example\n * ```typescript\n * const site = { domain: 'example.com', ... };\n * generateCanonicalUrlFromSlug(site, 'hello-world')\n * // 'https://example.com/blog/hello-world'\n * ```\n */\nexport function generateCanonicalUrlFromSlug(\n site: PublishedSite,\n slug: string,\n options: CanonicalUrlOptions = {}\n): string {\n return generateCanonicalUrl(\n {\n slug,\n site,\n // Minimal required fields for canonical URL generation\n id: '',\n title: '',\n excerpt: '',\n content: '',\n readingSeconds: 0,\n wordCount: 0,\n publishedAt: '',\n updatedAt: '',\n author: null,\n meta: { keywords: [] },\n version: 1\n },\n options\n );\n}\n\n/**\n * Validates if a URL is a valid canonical URL format.\n *\n * @param url - The URL to validate\n * @returns True if the URL is valid for canonical use\n *\n * @example\n * ```typescript\n * isValidCanonicalUrl('https://example.com/blog/hello-world') // true\n * isValidCanonicalUrl('http://example.com/blog/hello-world') // true\n * isValidCanonicalUrl('example.com/blog/hello-world') // false (missing protocol)\n * isValidCanonicalUrl('https://example.com/blog/hello world') // false (spaces)\n * ```\n */\nexport function isValidCanonicalUrl(url: string): boolean {\n try {\n const parsed = new URL(url);\n\n // Must be HTTP or HTTPS\n if (!['http:', 'https:'].includes(parsed.protocol)) {\n return false;\n }\n\n // Must have a valid hostname (not empty or just slashes)\n if (!parsed.hostname || parsed.hostname.length === 0) {\n return false;\n }\n\n // Check for URLs with empty hostname like 'https:///path'\n if (/^https?:\\/\\/\\//.exec(url) && !/^https?:\\/\\/[^\\/]/.exec(url)) {\n return false;\n }\n\n // Path should not contain unencoded spaces or other problematic characters\n // Check the original URL string since URL constructor auto-encodes\n if (url.includes(' ')) {\n return false;\n }\n\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Extracts the base URL (protocol + hostname + port) from a canonical URL.\n *\n * @param canonicalUrl - The canonical URL\n * @returns The base URL\n *\n * @example\n * ```typescript\n * getBaseUrl('https://example.com/blog/hello-world') // 'https://example.com'\n * getBaseUrl('https://blog.example.com:8080/posts/test') // 'https://blog.example.com:8080'\n * ```\n */\nexport function getBaseUrl(canonicalUrl: string): string {\n try {\n const parsed = new URL(canonicalUrl);\n return `${parsed.protocol}//${parsed.host}`;\n } catch {\n throw new Error('Invalid canonical URL provided');\n }\n}\n\n/**\n * Updates an article's canonical URL in its meta field.\n *\n * @param article - The article to update\n * @param options - Configuration options for URL generation\n * @returns A new article object with updated canonical URL\n *\n * @example\n * ```typescript\n * const updatedArticle = updateArticleCanonicalUrl(article);\n * console.log(updatedArticle.meta.canonicalUrl); // Generated canonical URL\n * ```\n */\nexport function updateArticleCanonicalUrl(\n article: PublishedArticle,\n options: CanonicalUrlOptions = {}\n): PublishedArticle {\n const canonicalUrl = generateCanonicalUrl(article, options);\n\n return {\n ...article,\n meta: {\n ...article.meta,\n canonicalUrl\n }\n };\n}","/**\n * Metadata generation utilities for SEO meta tags, OpenGraph, and Twitter Cards.\n *\n * These utilities create comprehensive metadata for blog articles and pages,\n * optimizing for search engines and social media sharing platforms.\n */\n\nimport type { PublishedArticle, PublishedSite } from '../types/contracts';\nimport { generateCanonicalUrl, type CanonicalUrlOptions } from './seo';\n\n/**\n * Configuration options for metadata generation.\n */\nexport interface MetadataOptions {\n /** Canonical URL generation options */\n canonical?: CanonicalUrlOptions;\n\n /** OpenGraph configuration */\n openGraph?: {\n /** Site name for OpenGraph */\n siteName?: string;\n /** Default OpenGraph image URL */\n defaultImage?: string;\n /** OpenGraph locale (defaults to site locale) */\n locale?: string;\n /** OpenGraph type (defaults to 'article') */\n type?: 'article' | 'website';\n };\n\n /** Twitter Card configuration */\n twitter?: {\n /** Twitter site handle (e.g., '@blogname') */\n site?: string;\n /** Twitter creator handle (e.g., '@authorname') */\n creator?: string;\n /** Default Twitter card type */\n cardType?: 'summary' | 'summary_large_image' | 'app' | 'player';\n };\n\n /** Additional meta tag configuration */\n meta?: {\n /** Robots meta tag directive */\n robots?: string;\n /** Viewport meta tag content */\n viewport?: string;\n /** Theme color for mobile browsers */\n themeColor?: string;\n /** Application name */\n applicationName?: string;\n };\n}\n\n/**\n * Generated metadata for HTML head section.\n */\nexport interface GeneratedMetadata {\n /** Basic HTML meta tags */\n meta: MetaTag[];\n\n /** OpenGraph meta tags */\n openGraph: MetaTag[];\n\n /** Twitter Card meta tags */\n twitter: MetaTag[];\n\n /** Link tags (canonical, etc.) */\n links: LinkTag[];\n\n /** Title tag content */\n title: string;\n\n /** Meta description content */\n description: string;\n\n /** Canonical URL */\n canonicalUrl: string;\n}\n\n/**\n * HTML meta tag representation.\n */\nexport interface MetaTag {\n name?: string;\n property?: string;\n content: string;\n httpEquiv?: string;\n}\n\n/**\n * HTML link tag representation.\n */\nexport interface LinkTag {\n rel: string;\n href: string;\n type?: string;\n title?: string;\n}\n\n/**\n * Generates comprehensive metadata for an article page.\n *\n * @param article - The published article\n * @param options - Metadata generation options\n * @returns Complete metadata for HTML head section\n *\n * @example\n * ```typescript\n * const metadata = generateArticleMetadata(article, {\n * openGraph: {\n * siteName: 'My Blog',\n * defaultImage: 'https://example.com/og-default.jpg'\n * },\n * twitter: {\n * site: '@myblog',\n * cardType: 'summary_large_image'\n * }\n * });\n * ```\n */\nexport function generateArticleMetadata(\n article: PublishedArticle,\n options: MetadataOptions = {}\n): GeneratedMetadata {\n const canonicalUrl = generateCanonicalUrl(article, options.canonical);\n const title = article.meta.title ?? article.title;\n const description = article.meta.description ?? article.excerpt;\n const siteName = options.openGraph?.siteName ?? article.site.name;\n\n // Basic meta tags\n const meta: MetaTag[] = [\n { name: 'description', content: description },\n { name: 'keywords', content: article.meta.keywords.join(', ') },\n { name: 'author', content: article.author?.name ?? siteName },\n { name: 'published_time', content: article.publishedAt },\n { name: 'modified_time', content: article.updatedAt },\n { name: 'article:reading_time', content: Math.ceil(article.readingSeconds / 60).toString() },\n ];\n\n // Add robots meta if specified\n if (options.meta?.robots) {\n meta.push({ name: 'robots', content: options.meta.robots });\n }\n\n // Add viewport meta if specified\n if (options.meta?.viewport) {\n meta.push({ name: 'viewport', content: options.meta.viewport });\n }\n\n // Add theme color if specified\n if (options.meta?.themeColor) {\n meta.push({ name: 'theme-color', content: options.meta.themeColor });\n }\n\n // Add application name if specified\n if (options.meta?.applicationName) {\n meta.push({ name: 'application-name', content: options.meta.applicationName });\n }\n\n // Generate OpenGraph metadata\n const openGraph = generateOpenGraphMetadata(article, canonicalUrl, {\n siteName,\n defaultImage: options.openGraph?.defaultImage,\n locale: options.openGraph?.locale ?? article.site.locale,\n type: options.openGraph?.type ?? 'article',\n });\n\n // Generate Twitter Card metadata\n const twitter = generateTwitterCardMetadata(article, {\n site: options.twitter?.site,\n creator: options.twitter?.creator,\n cardType: options.twitter?.cardType ?? 'summary_large_image',\n });\n\n // Generate link tags\n const links: LinkTag[] = [\n { rel: 'canonical', href: canonicalUrl },\n ];\n\n return {\n meta,\n openGraph,\n twitter,\n links,\n title,\n description,\n canonicalUrl,\n };\n}\n\n/**\n * Generates metadata for a blog home page or listing page.\n *\n * @param site - The published site information\n * @param options - Metadata generation options\n * @param pageInfo - Optional page-specific information\n * @returns Complete metadata for HTML head section\n *\n * @example\n * ```typescript\n * const metadata = generateSiteMetadata(site, {\n * openGraph: {\n * defaultImage: 'https://example.com/og-home.jpg'\n * }\n * }, {\n * title: 'Latest Articles',\n * description: 'Browse our latest blog posts',\n * path: '/blog'\n * });\n * ```\n */\nexport function generateSiteMetadata(\n site: PublishedSite,\n options: MetadataOptions = {},\n pageInfo?: {\n title?: string;\n description?: string;\n path?: string;\n pageNumber?: number;\n }\n): GeneratedMetadata {\n const path = pageInfo?.path ?? '/blog';\n const domain = options.canonical?.domain ?? site.domain;\n const canonicalUrl = `https://${domain}${path}`;\n\n const title = pageInfo?.title\n ? `${pageInfo.title} | ${site.name}`\n : site.name;\n\n const description = pageInfo?.description ?? site.description;\n const siteName = options.openGraph?.siteName ?? site.name;\n\n // Basic meta tags\n const meta: MetaTag[] = [\n { name: 'description', content: description },\n { name: 'author', content: siteName },\n ];\n\n // Add page number for pagination\n if (pageInfo?.pageNumber && pageInfo.pageNumber > 1) {\n meta.push({ name: 'page', content: pageInfo.pageNumber.toString() });\n }\n\n // Add robots meta if specified\n if (options.meta?.robots) {\n meta.push({ name: 'robots', content: options.meta.robots });\n }\n\n // Add viewport meta if specified\n if (options.meta?.viewport) {\n meta.push({ name: 'viewport', content: options.meta.viewport });\n }\n\n // Add theme color if specified\n if (options.meta?.themeColor) {\n meta.push({ name: 'theme-color', content: options.meta.themeColor });\n }\n\n // Add application name if specified\n if (options.meta?.applicationName) {\n meta.push({ name: 'application-name', content: options.meta.applicationName });\n }\n\n // Generate OpenGraph metadata for site\n const openGraph: MetaTag[] = [\n { property: 'og:title', content: title },\n { property: 'og:description', content: description },\n { property: 'og:url', content: canonicalUrl },\n { property: 'og:site_name', content: siteName },\n { property: 'og:locale', content: options.openGraph?.locale ?? site.locale },\n { property: 'og:type', content: options.openGraph?.type ?? 'website' },\n ];\n\n // Add default OpenGraph image if provided\n if (options.openGraph?.defaultImage) {\n openGraph.push(\n { property: 'og:image', content: options.openGraph.defaultImage },\n { property: 'og:image:alt', content: `${siteName} - ${site.tagline}` }\n );\n }\n\n // Generate Twitter Card metadata\n const twitter = generateTwitterCardMetadata(\n null, // No article for site pages\n {\n site: options.twitter?.site,\n creator: options.twitter?.creator,\n cardType: options.twitter?.cardType ?? 'summary',\n },\n {\n title,\n description,\n image: options.openGraph?.defaultImage,\n }\n );\n\n // Generate link tags\n const links: LinkTag[] = [\n { rel: 'canonical', href: canonicalUrl },\n ];\n\n return {\n meta,\n openGraph,\n twitter,\n links,\n title,\n description,\n canonicalUrl,\n };\n}\n\n/**\n * Generates OpenGraph metadata for an article.\n */\nfunction generateOpenGraphMetadata(\n article: PublishedArticle,\n canonicalUrl: string,\n options: {\n siteName: string;\n defaultImage?: string;\n locale: string;\n type: string;\n }\n): MetaTag[] {\n const title = article.meta.title ?? article.title;\n const description = article.meta.description ?? article.excerpt;\n const image = article.meta.ogImage ?? article.featuredImage ?? options.defaultImage;\n\n const openGraph: MetaTag[] = [\n { property: 'og:title', content: title },\n { property: 'og:description', content: description },\n { property: 'og:url', content: canonicalUrl },\n { property: 'og:site_name', content: options.siteName },\n { property: 'og:locale', content: options.locale },\n { property: 'og:type', content: options.type },\n { property: 'article:published_time', content: article.publishedAt },\n { property: 'article:modified_time', content: article.updatedAt },\n ];\n\n // Add image if available\n if (image) {\n const imageAlt = article.featuredImageAlt ?? `${article.title} - ${options.siteName}`;\n openGraph.push(\n { property: 'og:image', content: image },\n { property: 'og:image:alt', content: imageAlt }\n );\n }\n\n // Add author information\n if (article.author) {\n openGraph.push({ property: 'article:author', content: article.author.name });\n\n // Add author profile URL if we can construct one\n if (article.author.slug) {\n const authorUrl = canonicalUrl.replace(/\\/[^/]+$/, `/authors/${article.author.slug}`);\n openGraph.push({ property: 'article:author:url', content: authorUrl });\n }\n }\n\n // Add article tags from keywords\n article.meta.keywords.forEach(keyword => {\n openGraph.push({ property: 'article:tag', content: keyword });\n });\n\n // Add reading time\n const readingMinutes = Math.ceil(article.readingSeconds / 60);\n openGraph.push({ property: 'article:reading_time', content: readingMinutes.toString() });\n\n return openGraph;\n}\n\n/**\n * Generates Twitter Card metadata.\n */\nfunction generateTwitterCardMetadata(\n article: PublishedArticle | null,\n options: {\n site?: string;\n creator?: string;\n cardType: string;\n },\n overrides?: {\n title?: string;\n description?: string;\n image?: string;\n }\n): MetaTag[] {\n const title = overrides?.title ?? article?.meta.title ?? article?.title ?? '';\n const description = overrides?.description ?? article?.meta.description ?? article?.excerpt ?? '';\n const image = overrides?.image ?? article?.meta.ogImage ?? article?.featuredImage;\n\n const twitter: MetaTag[] = [\n { name: 'twitter:card', content: options.cardType },\n { name: 'twitter:title', content: title },\n { name: 'twitter:description', content: description },\n ];\n\n // Add site handle if provided\n if (options.site) {\n twitter.push({ name: 'twitter:site', content: options.site });\n }\n\n // Add creator handle if provided (for articles) or from options\n if (article?.author && options.creator) {\n twitter.push({ name: 'twitter:creator', content: options.creator });\n } else if (options.creator) {\n twitter.push({ name: 'twitter:creator', content: options.creator });\n }\n\n // Add image if available\n if (image) {\n twitter.push({ name: 'twitter:image', content: image });\n\n if (article?.featuredImageAlt) {\n twitter.push({ name: 'twitter:image:alt', content: article.featuredImageAlt });\n }\n }\n\n return twitter;\n}\n\n/**\n * Converts metadata to HTML string for server-side rendering.\n *\n * @param metadata - Generated metadata object\n * @returns HTML string for head section\n *\n * @example\n * ```typescript\n * const metadata = generateArticleMetadata(article);\n * const htmlHead = metadataToHtml(metadata);\n * // Use in server-side rendering\n * ```\n */\nexport function metadataToHtml(metadata: GeneratedMetadata): string {\n const elements: string[] = [];\n\n // Title\n elements.push(`<title>${escapeHtml(metadata.title)}</title>`);\n\n // Meta tags\n metadata.meta.forEach(tag => {\n const attrs: string[] = [];\n\n if (tag.name) attrs.push(`name=\"${escapeHtml(tag.name)}\"`);\n if (tag.property) attrs.push(`property=\"${escapeHtml(tag.property)}\"`);\n if (tag.httpEquiv) attrs.push(`http-equiv=\"${escapeHtml(tag.httpEquiv)}\"`);\n attrs.push(`content=\"${escapeHtml(tag.content)}\"`);\n\n elements.push(`<meta ${attrs.join(' ')} />`);\n });\n\n // OpenGraph tags\n metadata.openGraph.forEach(tag => {\n elements.push(`<meta property=\"${escapeHtml(tag.property!)}\" content=\"${escapeHtml(tag.content)}\" />`);\n });\n\n // Twitter tags\n metadata.twitter.forEach(tag => {\n elements.push(`<meta name=\"${escapeHtml(tag.name!)}\" content=\"${escapeHtml(tag.content)}\" />`);\n });\n\n // Link tags\n metadata.links.forEach(link => {\n const attrs: string[] = [];\n attrs.push(`rel=\"${escapeHtml(link.rel)}\"`);\n attrs.push(`href=\"${escapeHtml(link.href)}\"`);\n if (link.type) attrs.push(`type=\"${escapeHtml(link.type)}\"`);\n if (link.title) attrs.push(`title=\"${escapeHtml(link.title)}\"`);\n\n elements.push(`<link ${attrs.join(' ')} />`);\n });\n\n return elements.join('\\n');\n}\n\n/**\n * Escapes HTML special characters for safe inclusion in HTML attributes.\n */\nfunction escapeHtml(text: string): string {\n const htmlEscapes: Record<string, string> = {\n '&': '&amp;',\n '<': '&lt;',\n '>': '&gt;',\n '\"': '&quot;',\n \"'\": '&#x27;',\n };\n\n return text.replace(/[&<>\"']/g, char => htmlEscapes[char] ?? char);\n}\n\n/**\n * Validates that metadata meets SEO best practices.\n *\n * @param metadata - Generated metadata to validate\n * @returns Validation results with warnings and errors\n *\n * @example\n * ```typescript\n * const metadata = generateArticleMetadata(article);\n * const validation = validateMetadata(metadata);\n *\n * if (validation.errors.length > 0) {\n * console.error('Metadata errors:', validation.errors);\n * }\n * ```\n */\nexport function validateMetadata(metadata: GeneratedMetadata): {\n valid: boolean;\n errors: string[];\n warnings: string[];\n} {\n const errors: string[] = [];\n const warnings: string[] = [];\n\n // Title validation\n if (!metadata.title) {\n errors.push('Title is required');\n } else if (metadata.title.length > 60) {\n warnings.push('Title longer than 60 characters may be truncated in search results');\n } else if (metadata.title.length < 30) {\n warnings.push('Title shorter than 30 characters may not be descriptive enough');\n }\n\n // Description validation\n if (!metadata.description) {\n errors.push('Meta description is required');\n } else if (metadata.description.length > 160) {\n warnings.push('Meta description longer than 160 characters may be truncated');\n } else if (metadata.description.length < 120) {\n warnings.push('Meta description shorter than 120 characters may not be descriptive enough');\n }\n\n // Canonical URL validation\n if (!metadata.canonicalUrl) {\n errors.push('Canonical URL is required');\n } else if (!metadata.canonicalUrl.startsWith('https://')) {\n warnings.push('Canonical URL should use HTTPS for better SEO');\n }\n\n // OpenGraph validation\n const ogImage = metadata.openGraph.find(tag => tag.property === 'og:image');\n if (!ogImage) {\n warnings.push('OpenGraph image missing - social media sharing will not show image preview');\n }\n\n // Twitter Card validation\n const twitterCard = metadata.twitter.find(tag => tag.name === 'twitter:card');\n if (!twitterCard) {\n warnings.push('Twitter Card type missing - Twitter sharing may not display properly');\n }\n\n return {\n valid: errors.length === 0,\n errors,\n warnings,\n };\n}","/**\n * Next.js-compatible sitemap generation utilities for blog platform integration.\n *\n * These utilities generate sitemap entries that follow Next.js MetadataRoute.Sitemap\n * conventions, allowing seamless integration with existing Next.js applications.\n *\n * @example Integration with existing Next.js sitemap:\n * ```typescript\n * // app/sitemap.ts\n * import { generateBlogSitemapEntries } from '@xexr/blog-platform';\n * import type { MetadataRoute } from 'next';\n *\n * export default async function sitemap(): Promise<MetadataRoute.Sitemap> {\n * // Your existing routes\n * const staticRoutes = [\n * { url: 'https://yoursite.com', lastModified: new Date(), priority: 1 },\n * { url: 'https://yoursite.com/about', lastModified: new Date(), priority: 0.8 }\n * ];\n *\n * // Blog platform entries\n * const blogEntries = await generateBlogSitemapEntries(blogConfig);\n *\n * return [...staticRoutes, ...blogEntries];\n * }\n * ```\n */\n\nimport type {\n PublishedArticle,\n PublishedSite,\n PublishedAuthor,\n} from \"../types/contracts\";\nimport { getAuthorsFromArticles } from \"./authors\";\nimport {\n generateCanonicalUrl,\n normalizeDomain,\n type CanonicalUrlOptions,\n} from \"./seo\";\nimport { getAllTopics } from \"./topics\";\nimport { buildAuthorPath, buildBlogPath } from \"./urls\";\n\n/**\n * Configuration options for sitemap generation.\n */\nexport interface SitemapOptions {\n /** Canonical URL configuration */\n canonical?: CanonicalUrlOptions;\n\n /** Whether to include author pages in sitemap */\n includeAuthorPages?: boolean;\n\n /** Whether to include topic pages in sitemap */\n includeTopicPages?: boolean;\n\n /** Whether to include pagination pages in sitemap */\n includePaginationPages?: boolean;\n\n /** Number of articles per page for pagination calculation */\n articlesPerPage?: number;\n\n /** Maximum number of sitemap entries (defaults to 50,000 per Google guidelines) */\n maxEntries?: number;\n\n /** Change frequency for different page types */\n changeFrequency?: {\n /** Change frequency for blog home page */\n homePage?: SitemapChangeFreq;\n /** Change frequency for article pages */\n articles?: SitemapChangeFreq;\n /** Change frequency for author pages */\n authorPages?: SitemapChangeFreq;\n /** Change frequency for topic index and archive pages */\n topicPages?: SitemapChangeFreq;\n /** Change frequency for pagination pages */\n paginationPages?: SitemapChangeFreq;\n };\n\n /** Priority values for different page types */\n priority?: {\n /** Priority for blog home page (0.0-1.0) */\n homePage?: number;\n /** Priority for article pages (0.0-1.0) */\n articles?: number;\n /** Priority for author pages (0.0-1.0) */\n authorPages?: number;\n /** Priority for topic index and archive pages (0.0-1.0) */\n topicPages?: number;\n /** Priority for pagination pages (0.0-1.0) */\n paginationPages?: number;\n };\n}\n\n/**\n * Valid sitemap change frequency values as per XML sitemap standard.\n */\nexport type SitemapChangeFreq =\n | \"always\"\n | \"hourly\"\n | \"daily\"\n | \"weekly\"\n | \"monthly\"\n | \"yearly\"\n | \"never\";\n\n/**\n * Next.js MetadataRoute.Sitemap compatible entry.\n * This matches the expected format for Next.js sitemap generation.\n */\nexport interface NextjsSitemapEntry {\n /** The URL of the page */\n url: string;\n\n /** Last modification date */\n lastModified?: string | Date;\n\n /** Change frequency hint for search engines */\n changeFrequency?: SitemapChangeFreq;\n\n /** Priority relative to other URLs on the site (0.0-1.0) */\n priority?: number;\n\n /** Alternate language versions (for i18n) */\n alternates?: {\n languages?: Record<string, string>;\n };\n}\n\n/**\n * Legacy XML sitemap entry format (for backward compatibility).\n * @deprecated Use NextjsSitemapEntry for new implementations\n */\nexport interface SitemapEntry {\n /** The URL of the page */\n loc: string;\n\n /** Last modification date as ISO 8601 string */\n lastmod?: string;\n\n /** Change frequency hint for search engines */\n changefreq?: SitemapChangeFreq;\n\n /** Priority relative to other URLs on the site (0.0-1.0) */\n priority?: number;\n}\n\n/**\n * Complete sitemap data structure.\n */\nexport interface SitemapData {\n /** All URL entries in the sitemap */\n entries: SitemapEntry[];\n\n /** Total number of entries */\n totalEntries: number;\n\n /** Whether the sitemap was truncated due to size limits */\n truncated: boolean;\n\n /** Generation timestamp */\n generatedAt: string;\n\n /** Base URL used for canonical URL generation */\n baseUrl: string;\n}\n\n/**\n * Generates Next.js-compatible sitemap entries for blog platform integration.\n *\n * @param site - The published site information\n * @param articles - Array of published articles\n * @param authors - Array of published authors (optional)\n * @param options - Sitemap generation options\n * @returns Array of Next.js MetadataRoute.Sitemap compatible entries\n *\n * @example\n * ```typescript\n * // In your Next.js app/sitemap.ts file:\n * import { generateBlogSitemapEntries } from '@xexr/blog-platform';\n * import type { MetadataRoute } from 'next';\n *\n * export default async function sitemap(): Promise<MetadataRoute.Sitemap> {\n * const blogEntries = await generateBlogSitemapEntries(site, articles, authors, {\n * includeAuthorPages: true,\n * includePaginationPages: true,\n * changeFrequency: { articles: 'monthly' }\n * });\n *\n * return [\n * // Your existing site routes\n * { url: 'https://yoursite.com', lastModified: new Date(), priority: 1 },\n * { url: 'https://yoursite.com/about', lastModified: new Date() },\n * // Blog entries\n * ...blogEntries\n * ];\n * }\n * ```\n */\nexport async function generateBlogSitemapEntries(\n site: PublishedSite,\n articles: readonly PublishedArticle[],\n authors: readonly PublishedAuthor[] = [],\n options: SitemapOptions = {},\n): Promise<NextjsSitemapEntry[]> {\n const {\n includeAuthorPages = true,\n includeTopicPages = true,\n includePaginationPages = true,\n articlesPerPage = 10,\n maxEntries = 50000,\n changeFrequency = {},\n priority = {},\n } = options;\n\n const entries: NextjsSitemapEntry[] = [];\n const baseUrl = normalizeDomain(\n options.canonical?.domain ?? site.domain,\n options.canonical?.forceHttps ?? true,\n );\n\n const pathPrefix = options.canonical?.pathPrefix ?? \"/blog\";\n const sitemapAuthors =\n authors.length > 0 ? authors : getAuthorsFromArticles(articles);\n const sitemapTopics = getAllTopics([...articles]);\n\n // Add blog home page\n entries.push({\n url: `${baseUrl}${pathPrefix}`,\n lastModified: getLatestModificationDate(articles),\n changeFrequency: changeFrequency.homePage ?? \"daily\",\n priority: priority.homePage ?? 1.0,\n });\n\n // Add individual article pages\n articles.forEach((article) => {\n if (entries.length >= maxEntries) return;\n\n const articleUrl = generateCanonicalUrl(article, options.canonical);\n entries.push({\n url: articleUrl,\n lastModified: article.updatedAt,\n changeFrequency: changeFrequency.articles ?? \"monthly\",\n priority: priority.articles ?? 0.8,\n });\n });\n\n if (includeTopicPages && sitemapTopics.length > 0) {\n if (entries.length < maxEntries) {\n entries.push({\n url: `${baseUrl}${buildBlogPath(pathPrefix, \"topics\")}`,\n lastModified: getLatestModificationDate(articles),\n changeFrequency: changeFrequency.topicPages ?? \"weekly\",\n priority: priority.topicPages ?? 0.6,\n });\n }\n\n sitemapTopics.forEach((topic) => {\n if (entries.length >= maxEntries) return;\n\n const topicArticles = articles.filter((article) =>\n (article.topics ?? []).some((candidate) => candidate.slug === topic.slug),\n );\n\n entries.push({\n url: `${baseUrl}${buildBlogPath(pathPrefix, `topics/${topic.slug}`)}`,\n lastModified: getLatestModificationDate(topicArticles),\n changeFrequency: changeFrequency.topicPages ?? \"weekly\",\n priority: priority.topicPages ?? 0.6,\n });\n });\n }\n\n // Add author pages if enabled\n if (includeAuthorPages && sitemapAuthors.length > 0) {\n if (entries.length < maxEntries) {\n entries.push({\n url: `${baseUrl}${buildBlogPath(pathPrefix, \"authors\")}`,\n lastModified: getLatestModificationDate(articles),\n changeFrequency: changeFrequency.authorPages ?? \"weekly\",\n priority: priority.authorPages ?? 0.6,\n });\n }\n\n sitemapAuthors.forEach((author) => {\n if (entries.length >= maxEntries) return;\n\n const authorUrl = `${baseUrl}${buildAuthorPath(pathPrefix, author.slug)}`;\n\n // Find the latest article by this author for lastModified\n const authorArticles = articles.filter(\n (article) => article.author?.id === author.id,\n );\n const latestAuthorMod = getLatestModificationDate(authorArticles);\n\n entries.push({\n url: authorUrl,\n lastModified: latestAuthorMod,\n changeFrequency: changeFrequency.authorPages ?? \"weekly\",\n priority: priority.authorPages ?? 0.6,\n });\n });\n }\n\n // Add pagination pages if enabled\n if (includePaginationPages && articles.length > articlesPerPage) {\n const totalPages = Math.ceil(articles.length / articlesPerPage);\n\n for (let page = 2; page <= totalPages; page++) {\n if (entries.length >= maxEntries) break;\n\n entries.push({\n url: `${baseUrl}${pathPrefix}?page=${page}`,\n lastModified: getLatestModificationDate(articles),\n changeFrequency: changeFrequency.paginationPages ?? \"daily\",\n priority: priority.paginationPages ?? 0.5,\n });\n }\n }\n\n return entries;\n}\n\n/**\n * Legacy sitemap generation for backward compatibility.\n * @deprecated Use generateBlogSitemapEntries for Next.js integration\n *\n * @param site - The published site information\n * @param articles - Array of published articles\n * @param authors - Array of published authors (optional)\n * @param options - Sitemap generation options\n * @returns Complete sitemap data\n */\nexport function generateSitemap(\n site: PublishedSite,\n articles: readonly PublishedArticle[],\n authors: readonly PublishedAuthor[] = [],\n options: SitemapOptions = {},\n): SitemapData {\n const {\n includeAuthorPages = true,\n includeTopicPages = true,\n includePaginationPages = true,\n articlesPerPage = 10,\n maxEntries = 50000,\n changeFrequency = {},\n priority = {},\n } = options;\n\n const entries: SitemapEntry[] = [];\n const baseUrl = normalizeDomain(\n options.canonical?.domain ?? site.domain,\n options.canonical?.forceHttps ?? true,\n );\n\n const pathPrefix = options.canonical?.pathPrefix ?? \"/blog\";\n const generatedAt = new Date().toISOString();\n const sitemapAuthors =\n authors.length > 0 ? authors : getAuthorsFromArticles(articles);\n const sitemapTopics = getAllTopics([...articles]);\n\n // Calculate total potential entries to determine if truncation will occur\n let potentialEntries = 1; // Home page\n potentialEntries += articles.length; // Article pages\n if (includeTopicPages && sitemapTopics.length > 0) {\n potentialEntries += sitemapTopics.length + 1; // Topic index + topic pages\n }\n if (includeAuthorPages) {\n potentialEntries += sitemapAuthors.length > 0 ? sitemapAuthors.length + 1 : 0; // Authors index + author pages\n }\n if (includePaginationPages && articles.length > articlesPerPage) {\n const totalPages = Math.ceil(articles.length / articlesPerPage);\n potentialEntries += totalPages - 1; // Pagination pages (excluding page 1 which is home)\n }\n\n const willTruncate = potentialEntries > maxEntries;\n\n // Add blog home page\n entries.push({\n loc: `${baseUrl}${pathPrefix}`,\n lastmod: getLatestModificationDate(articles),\n changefreq: changeFrequency.homePage ?? \"daily\",\n priority: priority.homePage ?? 1.0,\n });\n\n // Add individual article pages\n articles.forEach((article) => {\n if (entries.length >= maxEntries) return;\n\n const articleUrl = generateCanonicalUrl(article, options.canonical);\n entries.push({\n loc: articleUrl,\n lastmod: article.updatedAt,\n changefreq: changeFrequency.articles ?? \"monthly\",\n priority: priority.articles ?? 0.8,\n });\n });\n\n if (includeTopicPages && sitemapTopics.length > 0) {\n if (entries.length < maxEntries) {\n entries.push({\n loc: `${baseUrl}${buildBlogPath(pathPrefix, \"topics\")}`,\n lastmod: getLatestModificationDate(articles),\n changefreq: changeFrequency.topicPages ?? \"weekly\",\n priority: priority.topicPages ?? 0.6,\n });\n }\n\n sitemapTopics.forEach((topic) => {\n if (entries.length >= maxEntries) return;\n\n const topicArticles = articles.filter((article) =>\n (article.topics ?? []).some((candidate) => candidate.slug === topic.slug),\n );\n\n entries.push({\n loc: `${baseUrl}${buildBlogPath(pathPrefix, `topics/${topic.slug}`)}`,\n lastmod: getLatestModificationDate(topicArticles),\n changefreq: changeFrequency.topicPages ?? \"weekly\",\n priority: priority.topicPages ?? 0.6,\n });\n });\n }\n\n // Add author pages if enabled\n if (includeAuthorPages && sitemapAuthors.length > 0) {\n if (entries.length < maxEntries) {\n entries.push({\n loc: `${baseUrl}${buildBlogPath(pathPrefix, \"authors\")}`,\n lastmod: getLatestModificationDate(articles),\n changefreq: changeFrequency.authorPages ?? \"weekly\",\n priority: priority.authorPages ?? 0.6,\n });\n }\n\n sitemapAuthors.forEach((author) => {\n if (entries.length >= maxEntries) return;\n\n const authorUrl = `${baseUrl}${buildAuthorPath(pathPrefix, author.slug)}`;\n\n // Find the latest article by this author for lastmod\n const authorArticles = articles.filter(\n (article) => article.author?.id === author.id,\n );\n const latestAuthorMod = getLatestModificationDate(authorArticles);\n\n entries.push({\n loc: authorUrl,\n lastmod: latestAuthorMod,\n changefreq: changeFrequency.authorPages ?? \"weekly\",\n priority: priority.authorPages ?? 0.6,\n });\n });\n }\n\n // Add pagination pages if enabled\n if (includePaginationPages && articles.length > articlesPerPage) {\n const totalPages = Math.ceil(articles.length / articlesPerPage);\n\n for (let page = 2; page <= totalPages; page++) {\n if (entries.length >= maxEntries) break;\n\n entries.push({\n loc: `${baseUrl}${pathPrefix}?page=${page}`,\n lastmod: getLatestModificationDate(articles),\n changefreq: changeFrequency.paginationPages ?? \"daily\",\n priority: priority.paginationPages ?? 0.5,\n });\n }\n }\n\n return {\n entries,\n totalEntries: entries.length,\n truncated: willTruncate,\n generatedAt,\n baseUrl,\n };\n}\n\n/**\n * Converts sitemap data to XML format.\n *\n * @param sitemapData - The sitemap data to convert\n * @returns XML string in sitemap format\n *\n * @example\n * ```typescript\n * const sitemap = generateSitemap(site, articles);\n * const xmlString = sitemapToXml(sitemap);\n * // Use in API route response\n * ```\n */\nexport function sitemapToXml(sitemapData: SitemapData): string {\n const xmlHeader = '<?xml version=\"1.0\" encoding=\"UTF-8\"?>';\n const urlsetOpen =\n '<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">';\n const urlsetClose = \"</urlset>\";\n\n const urlEntries = sitemapData.entries.map((entry) => {\n const elements: string[] = [];\n\n elements.push(` <url>`);\n elements.push(` <loc>${escapeXml(entry.loc)}</loc>`);\n\n if (entry.lastmod) {\n elements.push(` <lastmod>${escapeXml(entry.lastmod)}</lastmod>`);\n }\n\n if (entry.changefreq) {\n elements.push(\n ` <changefreq>${escapeXml(entry.changefreq)}</changefreq>`,\n );\n }\n\n if (entry.priority !== undefined) {\n elements.push(` <priority>${entry.priority.toFixed(1)}</priority>`);\n }\n\n elements.push(` </url>`);\n\n return elements.join(\"\\n\");\n });\n\n return [xmlHeader, urlsetOpen, ...urlEntries, urlsetClose].join(\"\\n\");\n}\n\n/**\n * Generates a sitemap index for large blogs that need multiple sitemaps.\n *\n * @param sitemaps - Array of sitemap information\n * @param baseUrl - Base URL for the site\n * @returns XML string for sitemap index\n *\n * @example\n * ```typescript\n * const sitemapIndex = generateSitemapIndex([\n * { url: 'https://example.com/sitemap-articles.xml', lastmod: '2023-01-01T00:00:00Z' },\n * { url: 'https://example.com/sitemap-authors.xml', lastmod: '2023-01-01T00:00:00Z' }\n * ], 'https://example.com');\n * ```\n */\nexport function generateSitemapIndex(\n sitemaps: readonly { url: string; lastmod?: string }[],\n _baseUrl: string,\n): string {\n const xmlHeader = '<?xml version=\"1.0\" encoding=\"UTF-8\"?>';\n const indexOpen =\n '<sitemapindex xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">';\n const indexClose = \"</sitemapindex>\";\n\n const sitemapEntries = sitemaps.map((sitemap) => {\n const elements: string[] = [];\n\n elements.push(` <sitemap>`);\n elements.push(` <loc>${escapeXml(sitemap.url)}</loc>`);\n\n if (sitemap.lastmod) {\n elements.push(` <lastmod>${escapeXml(sitemap.lastmod)}</lastmod>`);\n }\n\n elements.push(` </sitemap>`);\n\n return elements.join(\"\\n\");\n });\n\n return [xmlHeader, indexOpen, ...sitemapEntries, indexClose].join(\"\\n\");\n}\n\n/**\n * Validates sitemap data for compliance with search engine guidelines.\n *\n * @param sitemapData - The sitemap data to validate\n * @returns Validation results with errors and warnings\n *\n * @example\n * ```typescript\n * const sitemap = generateSitemap(site, articles);\n * const validation = validateSitemap(sitemap);\n *\n * if (validation.errors.length > 0) {\n * console.error('Sitemap errors:', validation.errors);\n * }\n * ```\n */\nexport function validateSitemap(sitemapData: SitemapData): {\n valid: boolean;\n errors: string[];\n warnings: string[];\n} {\n const errors: string[] = [];\n const warnings: string[] = [];\n\n // Check entry count\n if (sitemapData.entries.length === 0) {\n errors.push(\"Sitemap must contain at least one URL\");\n } else if (sitemapData.entries.length > 50000) {\n errors.push(\"Sitemap contains more than 50,000 URLs (Google limit)\");\n }\n\n // Check for truncation\n if (sitemapData.truncated) {\n warnings.push(\"Sitemap was truncated due to size limits\");\n }\n\n // Validate individual entries\n sitemapData.entries.forEach((entry, index) => {\n // Validate URL format\n try {\n new URL(entry.loc);\n } catch {\n errors.push(`Invalid URL at entry ${index + 1}: ${entry.loc}`);\n }\n\n // Validate priority range\n if (\n entry.priority !== undefined &&\n (entry.priority < 0 || entry.priority > 1)\n ) {\n errors.push(\n `Invalid priority at entry ${index + 1}: must be between 0.0 and 1.0`,\n );\n }\n\n // Validate lastmod format\n if (entry.lastmod && !isValidISODate(entry.lastmod)) {\n errors.push(\n `Invalid lastmod date at entry ${index + 1}: ${entry.lastmod}`,\n );\n }\n\n // Check URL length (Google limit is 2048 characters)\n if (entry.loc.length > 2048) {\n warnings.push(`URL at entry ${index + 1} exceeds 2048 character limit`);\n }\n });\n\n // Check for duplicate URLs\n const urlCounts = new Map<string, number>();\n sitemapData.entries.forEach((entry) => {\n const count = urlCounts.get(entry.loc) ?? 0;\n urlCounts.set(entry.loc, count + 1);\n });\n\n urlCounts.forEach((count, url) => {\n if (count > 1) {\n errors.push(`Duplicate URL found: ${url} (appears ${count} times)`);\n }\n });\n\n return {\n valid: errors.length === 0,\n errors,\n warnings,\n };\n}\n\n/**\n * Gets the latest modification date from an array of articles.\n */\nfunction getLatestModificationDate(\n articles: readonly PublishedArticle[],\n): string {\n if (articles.length === 0) {\n return new Date().toISOString();\n }\n\n const latestDate = articles.reduce((latest, article) => {\n const articleDate = new Date(article.updatedAt);\n return articleDate > latest ? articleDate : latest;\n }, new Date(articles[0]!.updatedAt));\n\n return latestDate.toISOString();\n}\n\n/**\n * Creates a separate sitemap specifically for blog content.\n * Useful for large sites that need to split sitemaps by content type.\n *\n * @param site - The published site information\n * @param articles - Array of published articles\n * @param authors - Array of published authors (optional)\n * @param options - Sitemap generation options\n * @returns Next.js sitemap function\n *\n * @example\n * ```typescript\n * // app/blog-sitemap/route.ts - separate blog sitemap endpoint\n * import { createBlogSitemapRoute } from '@xexr/blog-platform';\n *\n * export const GET = createBlogSitemapRoute(site, articles, authors, {\n * includeAuthorPages: true,\n * articlesPerPage: 20\n * });\n * ```\n */\nexport function createBlogSitemapRoute(\n site: PublishedSite,\n articles: readonly PublishedArticle[],\n authors: readonly PublishedAuthor[] = [],\n options: SitemapOptions = {},\n) {\n return async function GET() {\n const entries = await generateBlogSitemapEntries(\n site,\n articles,\n authors,\n options,\n );\n\n // Convert to Next.js sitemap format and return as XML\n const xmlEntries = entries.map((entry) => ({\n loc: entry.url,\n lastmod:\n typeof entry.lastModified === \"string\"\n ? entry.lastModified\n : entry.lastModified?.toISOString(),\n changefreq: entry.changeFrequency,\n priority: entry.priority,\n }));\n\n const sitemapData = {\n entries: xmlEntries,\n totalEntries: xmlEntries.length,\n truncated: false,\n generatedAt: new Date().toISOString(),\n baseUrl: normalizeDomain(\n options.canonical?.domain ?? site.domain,\n options.canonical?.forceHttps ?? true,\n ),\n };\n\n const xml = sitemapToXml(sitemapData);\n\n return new Response(xml, {\n headers: {\n \"Content-Type\": \"application/xml\",\n \"Cache-Control\": \"public, max-age=3600, s-maxage=3600\",\n },\n });\n };\n}\n\n/**\n * Configuration interface for blog data fetching.\n * Used to fetch blog data for sitemap generation.\n */\nexport interface BlogSitemapConfig {\n /** Static host app routes to include before Bloggy routes */\n staticRoutes?: readonly NextjsSitemapEntry[];\n\n /** Function to fetch static host app routes */\n getStaticRoutes?: () => Promise<readonly NextjsSitemapEntry[]>;\n\n /** Function to fetch site data */\n getSite: () => Promise<PublishedSite>;\n\n /** Function to fetch published articles */\n getArticles: () => Promise<readonly PublishedArticle[]>;\n\n /** Function to fetch authors (optional) */\n getAuthors?: () => Promise<readonly PublishedAuthor[]>;\n\n /** Sitemap generation options */\n options?: SitemapOptions;\n}\n\n/**\n * Higher-order function that creates a Next.js sitemap function with data fetching.\n * Ideal for dynamic blog content that needs to be fetched at sitemap generation time.\n *\n * @param config - Configuration for fetching blog data\n * @returns Next.js sitemap function\n *\n * @example\n * ```typescript\n * // app/sitemap.ts\n * import { createDynamicBlogSitemap } from '@xexr/blog-platform';\n * import { getBlogData } from './lib/blog';\n *\n * export default createDynamicBlogSitemap({\n * getSite: () => getBlogData().site,\n * getArticles: () => getBlogData().articles,\n * getAuthors: () => getBlogData().authors,\n * options: {\n * includeAuthorPages: true,\n * changeFrequency: { articles: 'weekly' }\n * }\n * });\n * ```\n */\nexport function createDynamicBlogSitemap(config: BlogSitemapConfig) {\n return async function sitemap(): Promise<NextjsSitemapEntry[]> {\n const staticRoutes = [\n ...(config.staticRoutes ?? []),\n ...(config.getStaticRoutes ? await config.getStaticRoutes() : []),\n ];\n const site = await config.getSite();\n const articles = await config.getArticles();\n const authors = config.getAuthors ? await config.getAuthors() : [];\n\n return [\n ...staticRoutes,\n ...(await generateBlogSitemapEntries(\n site,\n articles,\n authors,\n config.options,\n )),\n ];\n };\n}\n\n/**\n * Escapes special XML characters for safe inclusion in XML content.\n */\nfunction escapeXml(text: string): string {\n const xmlEscapes: Record<string, string> = {\n \"&\": \"&amp;\",\n \"<\": \"&lt;\",\n \">\": \"&gt;\",\n '\"': \"&quot;\",\n \"'\": \"&#x27;\",\n };\n\n return text.replace(/[&<>\"']/g, (char) => xmlEscapes[char] ?? char);\n}\n\n/**\n * Validates if a string is a valid ISO 8601 date.\n */\nfunction isValidISODate(dateString: string): boolean {\n try {\n const date = new Date(dateString);\n const isoString = date.toISOString();\n\n // Handle both formats: with and without milliseconds\n // 2023-01-01T00:00:00.000Z and 2023-01-01T00:00:00Z are both valid\n const normalizedInput =\n dateString.endsWith(\"Z\") && !dateString.includes(\".\")\n ? dateString.replace(\"Z\", \".000Z\")\n : dateString;\n\n return isoString === normalizedInput && !isNaN(date.getTime());\n } catch {\n return false;\n }\n}\n","{\n \"name\": \"@xexr/blog-platform\",\n \"version\": \"1.0.13\",\n \"description\": \"SEO-friendly blog platform for Next.js 15 with Bloggy integration\",\n \"main\": \"./dist/index.js\",\n \"types\": \"./dist/index.d.ts\",\n \"exports\": {\n \".\": {\n \"types\": \"./dist/index.d.ts\",\n \"import\": \"./dist/index.mjs\",\n \"require\": \"./dist/index.js\"\n },\n \"./types\": {\n \"types\": \"./dist/types/index.d.ts\",\n \"import\": \"./dist/types/index.mjs\",\n \"require\": \"./dist/types/index.js\"\n },\n \"./sitemap\": {\n \"types\": \"./dist/sitemap.d.ts\",\n \"import\": \"./dist/sitemap.mjs\",\n \"require\": \"./dist/sitemap.js\"\n },\n \"./app/blog/page\": {\n \"types\": \"./dist/app/blog/page.d.ts\",\n \"import\": \"./dist/app/blog/page.tsx\",\n \"default\": \"./dist/app/blog/page.tsx\"\n },\n \"./app/blog/[slug]/page\": {\n \"types\": \"./dist/app/blog/[slug]/page.d.ts\",\n \"import\": \"./dist/app/blog/[slug]/page.tsx\",\n \"default\": \"./dist/app/blog/[slug]/page.tsx\"\n },\n \"./app/*\": \"./dist/app/*\",\n \"./styles/*\": \"./dist/styles/*\"\n },\n \"files\": [\n \"dist/**/*\",\n \"README.md\",\n \"LICENSE\",\n \"CHANGELOG.md\"\n ],\n \"license\": \"MIT\",\n \"scripts\": {\n \"build\": \"tsup && node scripts/copy-dist-assets.mjs\",\n \"test\": \"vitest\",\n \"lint\": \"eslint src --max-warnings 0\",\n \"typecheck\": \"tsc --noEmit\",\n \"prepublishOnly\": \"pnpm run build\"\n },\n \"peerDependencies\": {\n \"@libsql/client\": \"^0.15.0\",\n \"drizzle-orm\": \"^0.44.0\",\n \"next\": \"^15.0.0 || ^16.0.0\",\n \"react\": \"^18.0.0 || ^19.0.0\",\n \"react-dom\": \"^18.0.0 || ^19.0.0\"\n },\n \"dependencies\": {\n \"@radix-ui/react-separator\": \"^1.1.8\",\n \"@radix-ui/react-slot\": \"^1.2.4\",\n \"@upstash/ratelimit\": \"^2.0.8\",\n \"@upstash/redis\": \"^1.37.0\",\n \"class-variance-authority\": \"^0.7.1\",\n \"clsx\": \"^2.1.1\",\n \"date-fns\": \"^4.1.0\",\n \"lucide-react\": \"^1.11.0\",\n \"next-mdx-remote-client\": \"^2.1.10\",\n \"react-icons\": \"^5.6.0\",\n \"rehype-slug\": \"^6.0.0\",\n \"remark-gfm\": \"^4.0.1\",\n \"remark-toc\": \"^9.0.0\",\n \"tailwind-merge\": \"^3.5.0\"\n },\n \"devDependencies\": {\n \"@types/react\": \"19.2.14\",\n \"tsup\": \"^8.5.1\",\n \"typescript\": \"^5.9.3\",\n \"vitest\": \"^4.1.5\"\n }\n}\n","// Import package.json for version info (works with resolveJsonModule)\nimport packageJson from \"../../package.json\";\n\n/**\n * Version information\n */\nexport interface VersionInfo {\n name: string;\n version: string;\n major: number;\n minor: number;\n patch: number;\n}\n\n/**\n * Version compatibility result\n */\nexport interface VersionCompatibilityResult {\n compatible: boolean;\n errorCode?: string;\n errorMessage?: string;\n warning?: string;\n}\n\n/**\n * Version compatibility error codes (matches PRD error codes)\n */\nexport const VERSION_ERROR_CODES = {\n PUB009: \"Major version incompatibility\",\n PUB010: \"Minor version warning\",\n} as const;\n\n/**\n * Parse semantic version string into components\n * @param version - Version string (e.g., \"1.2.3\")\n * @returns Parsed version components\n */\nfunction parseVersion(version: string): { major: number; minor: number; patch: number } {\n const cleaned = version.replace(/^v/, \"\"); // Remove 'v' prefix if present\n const parts = cleaned.split(\".\");\n \n if (parts.length < 3) {\n throw new Error(`Invalid version format: ${version}`);\n }\n \n const major = parseInt(parts[0] ?? \"0\", 10);\n const minor = parseInt(parts[1] ?? \"0\", 10);\n const patch = parseInt(parts[2]?.split(\"-\")[0] ?? \"0\", 10); // Handle pre-release versions\n \n if (isNaN(major) || isNaN(minor) || isNaN(patch)) {\n throw new Error(`Invalid version format: ${version}`);\n }\n \n return { major, minor, patch };\n}\n\n/**\n * Get blog platform package version (current package)\n * @returns Blog platform version information\n */\nexport function getBlogPlatformVersion(): VersionInfo {\n // Use imported package.json (works reliably in both CJS and ESM)\n const versionComponents = parseVersion(packageJson.version);\n\n return {\n name: packageJson.name,\n version: packageJson.version,\n ...versionComponents,\n };\n}\n\n/**\n * Parse version header from incoming request\n * Expected format: \"bloggy/1.0.0 platform/1.0.0\"\n * @param headerValue - Version header value\n * @returns Parsed version information or null if invalid\n */\nexport function parseVersionHeader(headerValue: string): {\n bloggyVersion?: VersionInfo;\n platformVersion?: VersionInfo;\n} | null {\n try {\n const parts = headerValue.split(\" \");\n const result: { bloggyVersion?: VersionInfo; platformVersion?: VersionInfo } = {};\n \n for (const part of parts) {\n const [name, version] = part.split(\"/\");\n if (!name || !version) continue;\n \n const versionComponents = parseVersion(version);\n const versionInfo: VersionInfo = {\n name: name,\n version: version,\n ...versionComponents,\n };\n \n if (name === \"bloggy\") {\n result.bloggyVersion = versionInfo;\n } else if (name === \"platform\") {\n result.platformVersion = versionInfo;\n }\n }\n \n return result;\n } catch {\n return null;\n }\n}\n\n/**\n * Check version compatibility between two versions\n * Based on semantic versioning rules:\n * - Major version differences are incompatible (PUB009)\n * - Minor version differences are warnings (PUB010)\n * - Patch version differences are acceptable\n * \n * @param version1 - First version\n * @param version2 - Second version\n * @returns Compatibility result\n */\nexport function checkVersionCompatibility(\n version1: VersionInfo,\n version2: VersionInfo,\n): VersionCompatibilityResult {\n try {\n // Major version incompatibility\n if (version1.major !== version2.major) {\n return {\n compatible: false,\n errorCode: \"PUB009\",\n errorMessage: `Major version incompatibility: ${version1.name} ${version1.version} is not compatible with ${version2.name} ${version2.version}. Please upgrade.`,\n };\n }\n \n // Minor version warning\n if (version1.minor !== version2.minor) {\n return {\n compatible: true,\n errorCode: \"PUB010\",\n warning: `Minor version difference: ${version1.name} ${version1.version} with ${version2.name} ${version2.version}. Some features may not be available.`,\n };\n }\n \n // Compatible (same major.minor, patch differences are okay)\n return {\n compatible: true,\n };\n } catch (error) {\n return {\n compatible: false,\n errorMessage: `Failed to check version compatibility: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n };\n }\n}","/**\n * Security headers for blog platform API endpoints\n *\n * This provides comprehensive security headers to protect against common\n * web vulnerabilities including XSS, clickjacking, and content injection.\n */\n\nimport type { NextRequest } from \"next/server\";\n\n/**\n * Security headers configuration interface\n */\nexport interface SecurityConfig {\n /** Enable Content Security Policy (default: true) */\n enableCSP?: boolean;\n\n /** Custom CSP directives (merges with defaults) */\n cspDirectives?: Record<string, string>;\n\n /** Enable X-Frame-Options (default: true) */\n enableFrameOptions?: boolean;\n\n /** X-Frame-Options value (default: \"DENY\") */\n frameOptions?: string;\n\n /** Enable X-Content-Type-Options (default: true) */\n enableContentTypeOptions?: boolean;\n\n /** Enable X-XSS-Protection (default: true) */\n enableXSSProtection?: boolean;\n\n /** Enable Referrer-Policy (default: true) */\n enableReferrerPolicy?: boolean;\n\n /** Referrer policy value (default: \"strict-origin-when-cross-origin\") */\n referrerPolicy?: string;\n\n /** Enable Strict-Transport-Security for HTTPS (default: true) */\n enableHSTS?: boolean;\n\n /** HSTS max-age in seconds (default: 31536000 = 1 year) */\n hstsMaxAge?: number;\n\n /** Include HSTS subdomains (default: true) */\n hstsIncludeSubdomains?: boolean;\n\n /** Enable Permissions-Policy (default: true) */\n enablePermissionsPolicy?: boolean;\n\n /** Custom permissions policy directives */\n permissionsPolicyDirectives?: Record<string, string>;\n}\n\n/**\n * Default security configuration for blog platform APIs\n */\nconst DEFAULT_SECURITY_CONFIG: Required<SecurityConfig> = {\n enableCSP: true,\n cspDirectives: {\n \"default-src\": \"'self'\",\n \"script-src\": \"'self' 'unsafe-inline'\", // Allow inline scripts for API responses\n \"style-src\": \"'self' 'unsafe-inline'\", // Allow inline styles for blog rendering\n \"img-src\": \"'self' data: https:\", // Allow images from self, data URIs, and HTTPS\n \"font-src\": \"'self' https:\", // Allow fonts from self and HTTPS\n \"connect-src\": \"'self'\", // API connections to same origin\n \"media-src\": \"'self'\", // Media from same origin only\n \"object-src\": \"'none'\", // Disable object/embed elements\n \"base-uri\": \"'self'\", // Restrict base URIs to same origin\n \"form-action\": \"'self'\", // Forms can only submit to same origin\n \"frame-ancestors\": \"'none'\", // Prevent embedding in frames\n \"upgrade-insecure-requests\": \"\", // Upgrade HTTP to HTTPS\n },\n enableFrameOptions: true,\n frameOptions: \"DENY\",\n enableContentTypeOptions: true,\n enableXSSProtection: true,\n enableReferrerPolicy: true,\n referrerPolicy: \"strict-origin-when-cross-origin\",\n enableHSTS: true,\n hstsMaxAge: 31536000, // 1 year\n hstsIncludeSubdomains: true,\n enablePermissionsPolicy: true,\n permissionsPolicyDirectives: {\n \"camera\": \"()\", // Disable camera access\n \"microphone\": \"()\", // Disable microphone access\n \"geolocation\": \"()\", // Disable geolocation\n \"payment\": \"()\", // Disable payment API\n \"usb\": \"()\", // Disable USB access\n \"accelerometer\": \"()\", // Disable accelerometer\n \"gyroscope\": \"()\", // Disable gyroscope\n \"magnetometer\": \"()\", // Disable magnetometer\n },\n};\n\n/**\n * Get security configuration from environment or defaults\n */\nfunction getSecurityConfig(): Required<SecurityConfig> {\n const envCSPDisabled = process.env.BLOG_PLATFORM_DISABLE_CSP === \"true\";\n const envFrameOptions = process.env.BLOG_PLATFORM_FRAME_OPTIONS;\n const envHSTSDisabled = process.env.BLOG_PLATFORM_DISABLE_HSTS === \"true\";\n\n return {\n ...DEFAULT_SECURITY_CONFIG,\n enableCSP: !envCSPDisabled,\n frameOptions: envFrameOptions ?? DEFAULT_SECURITY_CONFIG.frameOptions,\n enableHSTS: !envHSTSDisabled,\n };\n}\n\n/**\n * Build Content Security Policy header value\n */\nfunction buildCSPHeader(directives: Record<string, string>): string {\n return Object.entries(directives)\n .map(([directive, value]) =>\n value ? `${directive} ${value}` : directive\n )\n .join(\"; \");\n}\n\n/**\n * Build Permissions Policy header value\n */\nfunction buildPermissionsPolicyHeader(directives: Record<string, string>): string {\n return Object.entries(directives)\n .map(([feature, allowlist]) => `${feature}=${allowlist}`)\n .join(\", \");\n}\n\n/**\n * Get security headers for HTTP responses\n */\nexport function getSecurityHeaders(\n request: NextRequest,\n config: SecurityConfig = {}\n): Record<string, string> {\n const securityConfig = { ...getSecurityConfig(), ...config };\n const headers: Record<string, string> = {};\n\n // Content Security Policy\n if (securityConfig.enableCSP) {\n const cspDirectives = {\n ...securityConfig.cspDirectives,\n ...(config.cspDirectives ?? {}),\n };\n headers[\"Content-Security-Policy\"] = buildCSPHeader(cspDirectives);\n }\n\n // X-Frame-Options (prevent clickjacking)\n if (securityConfig.enableFrameOptions) {\n headers[\"X-Frame-Options\"] = securityConfig.frameOptions;\n }\n\n // X-Content-Type-Options (prevent MIME sniffing)\n if (securityConfig.enableContentTypeOptions) {\n headers[\"X-Content-Type-Options\"] = \"nosniff\";\n }\n\n // X-XSS-Protection (legacy XSS protection)\n if (securityConfig.enableXSSProtection) {\n headers[\"X-XSS-Protection\"] = \"1; mode=block\";\n }\n\n // Referrer-Policy (control referrer information)\n if (securityConfig.enableReferrerPolicy) {\n headers[\"Referrer-Policy\"] = securityConfig.referrerPolicy;\n }\n\n // Strict-Transport-Security (HTTPS enforcement)\n if (securityConfig.enableHSTS && isHTTPS(request)) {\n const hstsValue = [\n `max-age=${securityConfig.hstsMaxAge}`,\n securityConfig.hstsIncludeSubdomains ? \"includeSubDomains\" : \"\",\n ].filter(Boolean).join(\"; \");\n\n headers[\"Strict-Transport-Security\"] = hstsValue;\n }\n\n // Permissions-Policy (feature control)\n if (securityConfig.enablePermissionsPolicy) {\n const permissionsDirectives = {\n ...securityConfig.permissionsPolicyDirectives,\n ...(config.permissionsPolicyDirectives ?? {}),\n };\n headers[\"Permissions-Policy\"] = buildPermissionsPolicyHeader(permissionsDirectives);\n }\n\n return headers;\n}\n\n/**\n * Check if request is over HTTPS\n */\nfunction isHTTPS(request: NextRequest): boolean {\n // Check protocol from URL\n if (request.url.startsWith(\"https://\")) {\n return true;\n }\n\n // Check forwarded protocol headers (for proxies/load balancers)\n const forwardedProto = request.headers.get(\"x-forwarded-proto\");\n if (forwardedProto === \"https\") {\n return true;\n }\n\n // Check if we're in a secure context (Cloudflare, Vercel, etc.)\n const cfVisitor = request.headers.get(\"cf-visitor\");\n if (cfVisitor?.includes('\"scheme\":\"https\"')) {\n return true;\n }\n\n return false;\n}\n\n/**\n * Create security headers optimized for API endpoints\n */\nexport function getAPISecurityHeaders(\n request: NextRequest,\n config: SecurityConfig = {}\n): Record<string, string> {\n // API-specific CSP that's less restrictive for JSON responses\n const apiCSPDirectives = {\n \"default-src\": \"'none'\", // APIs don't need default sources\n \"frame-ancestors\": \"'none'\", // Prevent embedding\n \"base-uri\": \"'none'\", // No base URI needed for APIs\n };\n\n return getSecurityHeaders(request, {\n ...config,\n cspDirectives: {\n ...apiCSPDirectives,\n ...(config.cspDirectives ?? {}),\n },\n });\n}\n\n/**\n * Create security headers optimized for blog pages\n */\nexport function getBlogSecurityHeaders(\n request: NextRequest,\n config: SecurityConfig = {}\n): Record<string, string> {\n // Blog-specific CSP that allows images, fonts, and styles\n const blogCSPDirectives = {\n \"default-src\": \"'self'\",\n \"script-src\": \"'self' 'unsafe-inline'\",\n \"style-src\": \"'self' 'unsafe-inline' https:\",\n \"img-src\": \"'self' data: https:\",\n \"font-src\": \"'self' https:\",\n \"connect-src\": \"'self'\",\n \"frame-src\": \"'none'\", // No iframes in blog posts\n \"object-src\": \"'none'\", // No plugins/objects\n };\n\n return getSecurityHeaders(request, {\n ...config,\n frameOptions: \"SAMEORIGIN\", // Allow embedding from same origin\n cspDirectives: {\n ...blogCSPDirectives,\n ...(config.cspDirectives ?? {}),\n },\n });\n}\n\n/**\n * Security header presets for different use cases\n */\nexport const SECURITY_PRESETS = {\n /** Strict security for API endpoints */\n API: {\n enableCSP: true,\n frameOptions: \"DENY\",\n cspDirectives: {\n \"default-src\": \"'none'\",\n \"frame-ancestors\": \"'none'\",\n \"base-uri\": \"'none'\",\n },\n },\n\n /** Balanced security for blog pages */\n BLOG: {\n enableCSP: true,\n frameOptions: \"SAMEORIGIN\",\n cspDirectives: {\n \"default-src\": \"'self'\",\n \"script-src\": \"'self' 'unsafe-inline'\",\n \"style-src\": \"'self' 'unsafe-inline' https:\",\n \"img-src\": \"'self' data: https:\",\n \"font-src\": \"'self' https:\",\n },\n },\n\n /** Development-friendly settings */\n DEVELOPMENT: {\n enableCSP: false,\n enableHSTS: false,\n frameOptions: \"SAMEORIGIN\",\n },\n} as const;\n\n/**\n * Validate and sanitize CSP directive values\n */\nexport function sanitizeCSPDirective(directive: string, value: string): string {\n // Remove potentially dangerous values\n const sanitized = value\n .replace(/javascript:/gi, \"\") // Remove javascript: URIs\n .replace(/data:/gi, \"data:\") // Normalize data: URIs\n .replace(/\\s+/g, \" \") // Normalize whitespace\n .trim();\n\n // Validate that value doesn't contain injection attempts\n if (sanitized.includes(\";\") || sanitized.includes(\"\\n\") || sanitized.includes(\"\\r\")) {\n console.warn(`Potentially dangerous CSP value for ${directive}: ${value}`);\n return \"'none'\"; // Safe fallback\n }\n\n return sanitized;\n}","/**\n * CORS configuration for blog platform API endpoints\n * \n * This provides centralized CORS handling with security best practices\n * for cross-origin requests from Bloggy core applications.\n */\n\nimport type { NextRequest } from \"next/server\";\nimport { NextResponse } from \"next/server\";\nimport { getAPISecurityHeaders, type SecurityConfig } from \"./security-headers\";\n\n/**\n * CORS configuration interface\n */\nexport interface CorsConfig {\n /** Allowed origins (default: allow configured domains only) */\n allowedOrigins?: string[];\n\n /** Allow all origins with wildcard (default: false for security) */\n allowWildcard?: boolean;\n\n /** Allow credentials to be sent (default: false) */\n allowCredentials?: boolean;\n\n /** Cache preflight requests for this many seconds (default: 86400 = 24 hours) */\n maxAge?: number;\n\n /** Security headers configuration */\n securityConfig?: SecurityConfig;\n}\n\n/**\n * Default CORS configuration for blog platform\n */\nconst DEFAULT_CORS_CONFIG: Required<CorsConfig> = {\n allowedOrigins: [\n \"http://localhost:3000\", // Development Bloggy core\n \"https://localhost:3000\", // Development Bloggy core (HTTPS)\n \"http://127.0.0.1:3000\", // Alternative localhost\n \"https://127.0.0.1:3000\", // Alternative localhost (HTTPS)\n ],\n allowWildcard: false, // Security: don't allow all origins by default\n allowCredentials: false, // Security: don't allow credentials by default\n maxAge: 86400, // Cache preflight for 24 hours\n securityConfig: {}, // Default security configuration\n};\n\n/**\n * Get CORS configuration from environment or defaults\n */\nfunction getCorsConfig(): Required<CorsConfig> {\n const envOrigins = process.env.BLOG_PLATFORM_ALLOWED_ORIGINS;\n const allowWildcard = process.env.BLOG_PLATFORM_ALLOW_WILDCARD === \"true\";\n const allowCredentials = process.env.BLOG_PLATFORM_ALLOW_CREDENTIALS === \"true\";\n \n return {\n ...DEFAULT_CORS_CONFIG,\n allowedOrigins: envOrigins ? envOrigins.split(\",\").map(origin => origin.trim()) : DEFAULT_CORS_CONFIG.allowedOrigins,\n allowWildcard,\n allowCredentials,\n };\n}\n\n/**\n * Check if an origin is allowed based on CORS configuration\n */\nfunction isOriginAllowed(origin: string | null, config: Required<CorsConfig>): boolean {\n if (!origin) {\n return false;\n }\n \n // If wildcard is enabled, allow all origins\n if (config.allowWildcard) {\n return true;\n }\n \n // Check against allowed origins list\n return config.allowedOrigins.includes(origin);\n}\n\n/**\n * Get CORS headers for a given request and configuration\n */\nfunction getCorsHeaders(request: NextRequest, config: Required<CorsConfig>): Record<string, string> {\n const origin = request.headers.get(\"origin\");\n const headers: Record<string, string> = {};\n \n // Set allowed origin\n if (config.allowWildcard) {\n headers[\"Access-Control-Allow-Origin\"] = \"*\";\n } else if (origin && isOriginAllowed(origin, config)) {\n headers[\"Access-Control-Allow-Origin\"] = origin;\n }\n \n // Set credentials if allowed (only when not using wildcard)\n if (config.allowCredentials && !config.allowWildcard) {\n headers[\"Access-Control-Allow-Credentials\"] = \"true\";\n }\n \n // Always include Vary header when not using wildcard\n if (!config.allowWildcard) {\n headers.Vary = \"Origin\";\n }\n \n return headers;\n}\n\n/**\n * Get preflight CORS headers for OPTIONS requests\n */\nfunction getPreflightHeaders(\n request: NextRequest, \n config: Required<CorsConfig>,\n allowedMethods: string[],\n allowedHeaders: string[]\n): Record<string, string> {\n const corsHeaders = getCorsHeaders(request, config);\n \n return {\n ...corsHeaders,\n \"Access-Control-Allow-Methods\": allowedMethods.join(\", \"),\n \"Access-Control-Allow-Headers\": allowedHeaders.join(\", \"),\n \"Access-Control-Max-Age\": config.maxAge.toString(),\n };\n}\n\n/**\n * Standard allowed headers for blog platform API endpoints\n */\nexport const STANDARD_ALLOWED_HEADERS = [\n \"Content-Type\",\n \"X-Bloggy-Version\", \n \"X-Idempotency-Key\",\n \"Authorization\",\n \"X-Requested-With\",\n];\n\n/**\n * Create CORS-enabled response for API endpoints\n */\nexport function createCorsResponse<T>(\n request: NextRequest,\n data: T,\n options: {\n status?: number;\n headers?: Record<string, string>;\n corsConfig?: CorsConfig;\n } = {}\n): NextResponse<T> {\n const { status = 200, headers = {}, corsConfig = {} } = options;\n const config = { ...getCorsConfig(), ...corsConfig };\n\n const corsHeaders = getCorsHeaders(request, config);\n const securityHeaders = getAPISecurityHeaders(request, config.securityConfig);\n\n const responseHeaders = {\n \"Content-Type\": \"application/json\",\n ...corsHeaders,\n ...securityHeaders,\n ...headers,\n };\n\n return NextResponse.json(data, {\n status,\n headers: responseHeaders,\n });\n}\n\n/**\n * Handle CORS preflight OPTIONS requests\n */\nexport function handleCorsOptions(\n request: NextRequest,\n allowedMethods: string[],\n options: {\n allowedHeaders?: string[];\n corsConfig?: CorsConfig;\n } = {}\n): NextResponse {\n const { allowedHeaders = STANDARD_ALLOWED_HEADERS, corsConfig = {} } = options;\n const config = { ...getCorsConfig(), ...corsConfig };\n\n const origin = request.headers.get(\"origin\");\n\n // Check if origin is allowed\n if (origin && !config.allowWildcard && !isOriginAllowed(origin, config)) {\n const securityHeaders = getAPISecurityHeaders(request, config.securityConfig);\n return new NextResponse(null, {\n status: 403,\n headers: {\n \"Content-Type\": \"text/plain\",\n ...securityHeaders,\n },\n });\n }\n\n const preflightHeaders = getPreflightHeaders(\n request,\n config,\n [...allowedMethods, \"OPTIONS\"],\n allowedHeaders\n );\n\n const securityHeaders = getAPISecurityHeaders(request, config.securityConfig);\n\n return new NextResponse(null, {\n status: 200,\n headers: {\n ...preflightHeaders,\n ...securityHeaders,\n },\n });\n}\n\n/**\n * Middleware to add CORS headers to any response\n */\nexport function addCorsHeaders(\n request: NextRequest,\n response: NextResponse,\n corsConfig: CorsConfig = {}\n): NextResponse {\n const config = { ...getCorsConfig(), ...corsConfig };\n const corsHeaders = getCorsHeaders(request, config);\n const securityHeaders = getAPISecurityHeaders(request, config.securityConfig);\n\n // Add CORS and security headers to existing response\n Object.entries({ ...corsHeaders, ...securityHeaders }).forEach(([key, value]) => {\n response.headers.set(key, value);\n });\n\n return response;\n}\n\n/**\n * Check if request origin is allowed (utility for manual CORS checking)\n */\nexport function checkOriginAllowed(request: NextRequest, corsConfig: CorsConfig = {}): boolean {\n const config = { ...getCorsConfig(), ...corsConfig };\n const origin = request.headers.get(\"origin\");\n \n return isOriginAllowed(origin, config);\n}","import type { NextRequest, NextResponse } from \"next/server\";\nimport { getStorage } from \"@/lib/database\";\nimport { getBlogPlatformVersion, parseVersionHeader } from \"@/lib/version\";\nimport {\n requireAuth,\n authenticateRequest,\n createTokenFingerprint,\n} from \"@/lib/auth\";\nimport { enforceRateLimit, getRateLimitHeaders } from \"@/lib/ratelimit\";\nimport { createCorsResponse, handleCorsOptions } from \"@/lib/cors\";\nimport type {\n PublishPayload,\n PublishResult,\n PublishedArticle,\n} from \"@/types/contracts\";\n\n/**\n * POST /api/blog/publish\n *\n * Publishes an article to the blog platform with full idempotency support.\n * This endpoint receives content from Bloggy core and stores it for rendering.\n *\n * Request body should contain a PublishPayload with:\n * - article: The complete article data\n * - idempotencyKey: SHA-256 hash for duplicate prevention\n * - Optional overrides for slug, meta description, etc.\n */\nexport async function POST(\n request: NextRequest,\n): Promise<NextResponse<PublishResult>> {\n try {\n // Authenticate the request\n const auth = await authenticateRequest(request);\n if (!auth.authenticated) {\n const authCheck = await requireAuth(request);\n return createCorsResponse(request, authCheck.error!, { status: 401 });\n }\n\n // Apply rate limiting without exposing raw authentication tokens to Redis.\n const tokenFingerprint = createTokenFingerprint(auth.token ?? \"anonymous\");\n const rateLimitCheck = await enforceRateLimit(tokenFingerprint);\n if (!rateLimitCheck.allowed) {\n // Extract rate limit info from error response, with safe fallback\n const rateLimitData =\n rateLimitCheck.errorResponse.error?.details?.rateLimit;\n const rateLimitResult =\n rateLimitData &&\n typeof rateLimitData === \"object\" &&\n \"limit\" in rateLimitData &&\n \"remaining\" in rateLimitData &&\n \"reset\" in rateLimitData &&\n \"count\" in rateLimitData &&\n \"success\" in rateLimitData\n ? (rateLimitData as {\n limit: number;\n remaining: number;\n reset: number;\n count: number;\n success: boolean;\n })\n : {\n limit: 10,\n remaining: 0,\n reset: Date.now() + 60000,\n count: 10,\n success: false,\n };\n\n const rateLimitHeaders = getRateLimitHeaders(rateLimitResult);\n\n return createCorsResponse(request, rateLimitCheck.errorResponse, {\n status: 429,\n headers: rateLimitHeaders,\n });\n }\n\n // Validate request content type\n const contentType = request.headers.get(\"content-type\");\n if (!contentType?.includes(\"application/json\")) {\n return createCorsResponse(\n request,\n {\n success: false,\n error: {\n code: \"PUB001\",\n message: \"Content-Type must be application/json\",\n },\n idempotencyKey: \"\",\n },\n { status: 400 },\n );\n }\n\n // Parse request body\n let payload: PublishPayload;\n try {\n payload = (await request.json()) as PublishPayload;\n } catch {\n return createCorsResponse(\n request,\n {\n success: false,\n error: {\n code: \"PUB001\",\n message: \"Invalid JSON in request body\",\n },\n idempotencyKey: \"\",\n },\n { status: 400 },\n );\n }\n\n // Validate required fields\n const validationErrors = validatePublishPayload(payload);\n if (validationErrors.length > 0) {\n return createCorsResponse(\n request,\n {\n success: false,\n error: {\n code: \"PUB001\",\n message: \"Missing required fields\",\n details: { errors: validationErrors },\n },\n idempotencyKey: payload.idempotencyKey ?? \"\",\n },\n { status: 400 },\n );\n }\n\n // Check version compatibility if header provided\n const clientVersionHeader = request.headers.get(\"X-Bloggy-Version\");\n if (clientVersionHeader) {\n const parsedVersions = parseVersionHeader(clientVersionHeader);\n if (parsedVersions?.platformVersion) {\n const platformVersion = getBlogPlatformVersion();\n\n // Check for major version incompatibility\n if (parsedVersions.platformVersion.major !== platformVersion.major) {\n return createCorsResponse(\n request,\n {\n success: false,\n error: {\n code: \"PUB009\",\n message:\n \"Major version incompatibility. Please upgrade your blog platform package.\",\n details: {\n clientVersion: parsedVersions.platformVersion.version,\n serverVersion: platformVersion.version,\n },\n },\n idempotencyKey: payload.idempotencyKey,\n },\n { status: 409 },\n );\n }\n }\n }\n\n // Handle dry run validation\n if (payload.dryRun) {\n const warnings: string[] = [];\n\n // Validate content requirements\n if (payload.article.wordCount < 50) {\n warnings.push(\"Article has fewer than 50 words, which may affect SEO\");\n }\n\n if (!payload.article.excerpt || payload.article.excerpt.length < 120) {\n warnings.push(\n \"Article excerpt is shorter than recommended 120 characters\",\n );\n }\n\n if (!payload.article.meta.keywords.length) {\n warnings.push(\"No SEO keywords provided\");\n }\n\n return createCorsResponse(\n request,\n {\n success: true,\n warnings,\n idempotencyKey: payload.idempotencyKey,\n },\n { status: 200 },\n );\n }\n\n // Prepare the article with any overrides\n const finalArticle: PublishedArticle = {\n ...payload.article,\n slug: payload.slug ?? payload.article.slug,\n meta: {\n ...payload.article.meta,\n description:\n payload.metaDescription ?? payload.article.meta.description,\n },\n };\n\n // Validate slug format\n if (!isValidSlug(finalArticle.slug)) {\n return createCorsResponse(\n request,\n {\n success: false,\n error: {\n code: \"PUB002\",\n message:\n \"Slug can only contain lowercase letters, numbers, and hyphens\",\n },\n idempotencyKey: payload.idempotencyKey,\n },\n { status: 400 },\n );\n }\n\n // Get storage and attempt to save\n const storage = getStorage();\n const result = await storage.saveArticle(\n finalArticle,\n payload.idempotencyKey,\n );\n\n // Prepare response headers\n const platformVersion = getBlogPlatformVersion();\n const rateLimitHeaders = getRateLimitHeaders(\n rateLimitCheck.rateLimitResult,\n );\n\n const responseHeaders: Record<string, string> = {\n \"X-Bloggy-Version\": `platform/${platformVersion.version}`,\n \"X-Idempotency-Key\": payload.idempotencyKey,\n ...rateLimitHeaders,\n };\n\n if (result.success) {\n responseHeaders.Location = result.url ?? `/${finalArticle.slug}`;\n }\n\n // Return appropriate status code\n const statusCode = result.success\n ? 201\n : result.error?.code === \"PUB003\"\n ? 409\n : 400;\n\n return createCorsResponse(request, result, {\n status: statusCode,\n headers: responseHeaders,\n });\n } catch (error) {\n console.error(\"Publish endpoint error:\", error);\n\n const errorResult: PublishResult = {\n success: false,\n error: {\n code: \"PUB007\",\n message: \"Internal server error during publishing\",\n },\n idempotencyKey: \"\",\n };\n\n return createCorsResponse(request, errorResult, { status: 500 });\n }\n}\n\n/**\n * OPTIONS /api/blog/publish\n *\n * Handle CORS preflight requests\n */\nexport async function OPTIONS(request: NextRequest): Promise<NextResponse> {\n return handleCorsOptions(request, [\"POST\"], {\n allowedHeaders: [\n \"Content-Type\",\n \"X-Bloggy-Version\",\n \"X-Idempotency-Key\",\n \"Authorization\",\n \"X-Requested-With\",\n ],\n });\n}\n\n/**\n * Validate the publish payload structure\n */\nfunction validatePublishPayload(payload: unknown): string[] {\n const errors: string[] = [];\n\n if (!payload || typeof payload !== \"object\") {\n errors.push(\"Request body must be a valid object\");\n return errors;\n }\n\n const p = payload as Record<string, unknown>;\n\n // Check required top-level fields\n if (!p.article || typeof p.article !== \"object\") {\n errors.push(\"Missing required field: article\");\n }\n\n if (!p.idempotencyKey || typeof p.idempotencyKey !== \"string\") {\n errors.push(\"Missing required field: idempotencyKey\");\n }\n\n // Validate article structure if present\n if (p.article && typeof p.article === \"object\") {\n const article = p.article as Record<string, unknown>;\n\n const requiredFields = [\n \"id\",\n \"slug\",\n \"title\",\n \"content\",\n \"publishedAt\",\n \"site\",\n ];\n for (const field of requiredFields) {\n if (!article[field]) {\n errors.push(`Missing required article field: ${field}`);\n }\n }\n\n // Validate site structure\n if (article.site && typeof article.site === \"object\") {\n const site = article.site as Record<string, unknown>;\n const requiredSiteFields = [\"id\", \"name\", \"domain\"];\n for (const field of requiredSiteFields) {\n if (!site[field]) {\n errors.push(`Missing required site field: ${field}`);\n }\n }\n }\n\n // Validate meta structure\n if (article.meta && typeof article.meta === \"object\") {\n const meta = article.meta as Record<string, unknown>;\n if (!Array.isArray(meta.keywords)) {\n errors.push(\"Article meta.keywords must be an array\");\n }\n }\n }\n\n return errors;\n}\n\n/**\n * Validate slug format\n * Must be lowercase, alphanumeric, and hyphens only\n */\nfunction isValidSlug(slug: string): boolean {\n if (!slug || typeof slug !== \"string\") {\n return false;\n }\n\n // Allow lowercase letters, numbers, and hyphens\n // Must start and end with alphanumeric character\n const slugRegex = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;\n return slugRegex.test(slug) && slug.length >= 1 && slug.length <= 100;\n}\n\nexport { isValidSlug };\n","import { type NextRequest, NextResponse } from \"next/server\";\nimport { getStorage } from \"@/lib/database\";\nimport { getBlogPlatformVersion, parseVersionHeader } from \"@/lib/version\";\nimport {\n requireAuth,\n authenticateRequest,\n createTokenFingerprint,\n} from \"@/lib/auth\";\nimport { enforceRateLimit, getRateLimitHeaders } from \"@/lib/ratelimit\";\nimport { createCorsResponse, handleCorsOptions } from \"@/lib/cors\";\nimport type { UnpublishPayload, PublishResult } from \"@/types/contracts\";\n\n/**\n * POST /api/blog/unpublish\n *\n * Unpublishes an article from the blog platform with full idempotency support.\n * This endpoint receives unpublish requests from Bloggy core and removes the content.\n *\n * Request body should contain an UnpublishPayload with:\n * - slug: The article slug to unpublish\n * - idempotencyKey: SHA-256 hash for duplicate prevention\n * - Optional dry run flag for validation\n */\nexport async function POST(\n request: NextRequest,\n): Promise<NextResponse<PublishResult>> {\n try {\n // Authenticate the request\n const auth = await authenticateRequest(request);\n if (!auth.authenticated) {\n const authCheck = await requireAuth(request);\n return NextResponse.json(authCheck.error!, { status: 401 });\n }\n\n // Apply rate limiting without exposing raw authentication tokens to Redis.\n const tokenFingerprint = createTokenFingerprint(auth.token ?? \"anonymous\");\n const rateLimitCheck = await enforceRateLimit(tokenFingerprint);\n if (!rateLimitCheck.allowed) {\n // Extract rate limit info from error response, with safe fallback\n const rateLimitData =\n rateLimitCheck.errorResponse.error?.details?.rateLimit;\n const rateLimitResult =\n rateLimitData &&\n typeof rateLimitData === \"object\" &&\n \"limit\" in rateLimitData &&\n \"remaining\" in rateLimitData &&\n \"reset\" in rateLimitData &&\n \"count\" in rateLimitData &&\n \"success\" in rateLimitData\n ? (rateLimitData as {\n limit: number;\n remaining: number;\n reset: number;\n count: number;\n success: boolean;\n })\n : {\n limit: 10,\n remaining: 0,\n reset: Date.now() + 60000,\n count: 10,\n success: false,\n };\n\n const rateLimitHeaders = getRateLimitHeaders(rateLimitResult);\n\n return createCorsResponse(request, rateLimitCheck.errorResponse, {\n status: 429,\n headers: rateLimitHeaders,\n });\n }\n\n // Validate request content type\n const contentType = request.headers.get(\"content-type\");\n if (!contentType?.includes(\"application/json\")) {\n return createCorsResponse(\n request,\n {\n success: false,\n error: {\n code: \"PUB001\",\n message: \"Content-Type must be application/json\",\n },\n idempotencyKey: \"\",\n },\n { status: 400 },\n );\n }\n\n // Parse request body\n let payload: UnpublishPayload;\n try {\n payload = (await request.json()) as UnpublishPayload;\n } catch {\n return createCorsResponse(\n request,\n {\n success: false,\n error: {\n code: \"PUB001\",\n message: \"Invalid JSON in request body\",\n },\n idempotencyKey: \"\",\n },\n { status: 400 },\n );\n }\n\n // Validate required fields\n const validationErrors = validateUnpublishPayload(payload);\n if (validationErrors.length > 0) {\n return createCorsResponse(\n request,\n {\n success: false,\n error: {\n code: \"PUB001\",\n message: \"Missing required fields\",\n details: { errors: validationErrors },\n },\n idempotencyKey: payload.idempotencyKey ?? \"\",\n },\n { status: 400 },\n );\n }\n\n // Check version compatibility if header provided\n const clientVersionHeader = request.headers.get(\"X-Bloggy-Version\");\n if (clientVersionHeader) {\n const parsedVersions = parseVersionHeader(clientVersionHeader);\n if (parsedVersions?.platformVersion) {\n const platformVersion = getBlogPlatformVersion();\n\n // Check for major version incompatibility\n if (parsedVersions.platformVersion.major !== platformVersion.major) {\n return createCorsResponse(\n request,\n {\n success: false,\n error: {\n code: \"PUB009\",\n message:\n \"Major version incompatibility. Please upgrade your blog platform package.\",\n details: {\n clientVersion: parsedVersions.platformVersion.version,\n serverVersion: platformVersion.version,\n },\n },\n idempotencyKey: payload.idempotencyKey,\n },\n { status: 409 },\n );\n }\n }\n }\n\n // Validate slug format\n if (!isValidSlug(payload.slug)) {\n return createCorsResponse(\n request,\n {\n success: false,\n error: {\n code: \"PUB002\",\n message:\n \"Slug can only contain lowercase letters, numbers, and hyphens\",\n },\n idempotencyKey: payload.idempotencyKey,\n },\n { status: 400 },\n );\n }\n\n // Handle dry run validation\n if (payload.dryRun) {\n const storage = getStorage();\n const existingArticle = await storage.getArticle(payload.slug);\n\n const warnings: string[] = [];\n if (!existingArticle) {\n warnings.push(\"Article with this slug does not exist\");\n }\n\n return createCorsResponse(\n request,\n {\n success: true,\n warnings,\n idempotencyKey: payload.idempotencyKey,\n },\n { status: 200 },\n );\n }\n\n // Get storage and attempt to remove article\n const storage = getStorage();\n const result = await storage.removeArticle(\n payload.slug,\n payload.idempotencyKey,\n );\n\n // Prepare response headers\n const platformVersion = getBlogPlatformVersion();\n const rateLimitHeaders = getRateLimitHeaders(\n rateLimitCheck.rateLimitResult,\n );\n\n const responseHeaders = {\n \"X-Bloggy-Version\": `platform/${platformVersion.version}`,\n \"X-Idempotency-Key\": payload.idempotencyKey,\n ...rateLimitHeaders,\n };\n\n // Return appropriate status code\n const statusCode = result.success\n ? 200\n : result.error?.code === \"PUB007\"\n ? 404\n : 400;\n\n return createCorsResponse(request, result, {\n status: statusCode,\n headers: responseHeaders,\n });\n } catch (error) {\n console.error(\"Unpublish endpoint error:\", error);\n\n const errorResult: PublishResult = {\n success: false,\n error: {\n code: \"PUB007\",\n message: \"Internal server error during unpublishing\",\n },\n idempotencyKey: \"\",\n };\n\n return createCorsResponse(request, errorResult, { status: 500 });\n }\n}\n\n/**\n * DELETE /api/blog/unpublish\n *\n * Alternative HTTP method for unpublishing (some clients prefer DELETE for removal operations)\n * Accepts the same payload structure as POST\n */\nexport async function DELETE(\n request: NextRequest,\n): Promise<NextResponse<PublishResult>> {\n return POST(request);\n}\n\n/**\n * OPTIONS /api/blog/unpublish\n *\n * Handle CORS preflight requests\n */\nexport async function OPTIONS(request: NextRequest): Promise<NextResponse> {\n return handleCorsOptions(request, [\"POST\", \"DELETE\"]);\n}\n\n/**\n * Validate the unpublish payload structure\n */\nfunction validateUnpublishPayload(payload: unknown): string[] {\n const errors: string[] = [];\n\n if (!payload || typeof payload !== \"object\") {\n errors.push(\"Request body must be a valid object\");\n return errors;\n }\n\n const p = payload as Record<string, unknown>;\n\n // Check required fields\n if (!p.slug || typeof p.slug !== \"string\") {\n errors.push(\"Missing required field: slug\");\n }\n\n if (!p.idempotencyKey || typeof p.idempotencyKey !== \"string\") {\n errors.push(\"Missing required field: idempotencyKey\");\n }\n\n // Validate slug is not empty\n if (p.slug && typeof p.slug === \"string\" && !p.slug.trim()) {\n errors.push(\"Slug cannot be empty\");\n }\n\n return errors;\n}\n\n/**\n * Validate slug format\n * Must be lowercase, alphanumeric, and hyphens only\n */\nfunction isValidSlug(slug: string): boolean {\n if (!slug || typeof slug !== \"string\") {\n return false;\n }\n\n // Allow lowercase letters, numbers, and hyphens\n // Must start and end with alphanumeric character\n const slugRegex = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;\n return slugRegex.test(slug) && slug.length >= 1 && slug.length <= 100;\n}\n","import type { NextRequest, NextResponse } from \"next/server\";\nimport {\n getBlogPlatformVersion,\n parseVersionHeader,\n checkVersionCompatibility,\n type VersionCompatibilityResult,\n type VersionInfo,\n} from \"@/lib/version\";\nimport {\n requireAuth,\n authenticateRequest,\n createTokenFingerprint,\n} from \"@/lib/auth\";\nimport { enforceRateLimit, getRateLimitHeaders } from \"@/lib/ratelimit\";\nimport { createCorsResponse, handleCorsOptions } from \"@/lib/cors\";\n\n/**\n * Version compatibility response\n */\ninterface VersionResponse {\n success: boolean;\n versions: {\n bloggy: VersionInfo;\n platform: VersionInfo;\n };\n compatibility: VersionCompatibilityResult;\n error?: string;\n}\n\n/**\n * GET /api/blog/version\n *\n * Returns version information and compatibility status for Bloggy core and blog platform.\n * Used by customers to verify compatibility before publishing.\n *\n * Optional X-Bloggy-Version header can be provided to check compatibility\n * with specific versions.\n */\nexport async function GET(\n request: NextRequest,\n): Promise<NextResponse<VersionResponse>> {\n try {\n // Authenticate the request\n const auth = await authenticateRequest(request);\n if (!auth.authenticated) {\n const authCheck = await requireAuth(request);\n const errorResponse: VersionResponse = {\n success: false,\n versions: {\n bloggy: {\n name: \"unknown\",\n version: \"unknown\",\n major: 0,\n minor: 0,\n patch: 0,\n },\n platform: {\n name: \"unknown\",\n version: \"unknown\",\n major: 0,\n minor: 0,\n patch: 0,\n },\n },\n compatibility: {\n compatible: false,\n errorMessage:\n authCheck.error?.error?.message ?? \"Authentication required\",\n },\n };\n return createCorsResponse(request, errorResponse, { status: 401 });\n }\n\n // Apply rate limiting without exposing raw authentication tokens to Redis.\n const tokenFingerprint = createTokenFingerprint(auth.token ?? \"anonymous\");\n const rateLimitCheck = await enforceRateLimit(tokenFingerprint);\n if (!rateLimitCheck.allowed) {\n // Extract rate limit info from error response, with safe fallback\n const rateLimitData =\n rateLimitCheck.errorResponse.error?.details?.rateLimit;\n const rateLimitResult =\n rateLimitData &&\n typeof rateLimitData === \"object\" &&\n \"limit\" in rateLimitData &&\n \"remaining\" in rateLimitData &&\n \"reset\" in rateLimitData &&\n \"count\" in rateLimitData &&\n \"success\" in rateLimitData\n ? (rateLimitData as {\n limit: number;\n remaining: number;\n reset: number;\n count: number;\n success: boolean;\n })\n : {\n limit: 10,\n remaining: 0,\n reset: Date.now() + 60000,\n count: 10,\n success: false,\n };\n\n const rateLimitHeaders = getRateLimitHeaders(rateLimitResult);\n\n // Create a proper version response with error\n const errorVersionResponse: VersionResponse = {\n success: false,\n versions: {\n bloggy: {\n name: \"unknown\",\n version: \"unknown\",\n major: 0,\n minor: 0,\n patch: 0,\n },\n platform: {\n name: \"unknown\",\n version: \"unknown\",\n major: 0,\n minor: 0,\n patch: 0,\n },\n },\n compatibility: {\n compatible: false,\n errorMessage:\n rateLimitCheck.errorResponse.error?.message ??\n \"Rate limit exceeded\",\n },\n };\n\n return createCorsResponse(request, errorVersionResponse, {\n status: 429,\n headers: rateLimitHeaders,\n });\n }\n\n // Get current platform version information\n const platformVersion = getBlogPlatformVersion();\n\n // Parse Bloggy version from X-Bloggy-Version header\n const clientVersionHeader = request.headers.get(\"X-Bloggy-Version\");\n let bloggyVersion: VersionInfo = {\n name: \"unknown\",\n version: \"unknown\",\n major: 0,\n minor: 0,\n patch: 0,\n };\n\n if (clientVersionHeader) {\n try {\n // Try parsing as simple version string first (e.g., \"0.1.0\")\n if (/^\\d+\\.\\d+\\.\\d+/.test(clientVersionHeader)) {\n const parts = clientVersionHeader.split(\".\");\n const major = parseInt(parts[0] ?? \"0\", 10);\n const minor = parseInt(parts[1] ?? \"0\", 10);\n const patch = parseInt(parts[2]?.split(\"-\")[0] ?? \"0\", 10);\n\n bloggyVersion = {\n name: \"bloggy\",\n version: clientVersionHeader,\n major,\n minor,\n patch,\n };\n } else {\n // Try parsing as formatted header (e.g., \"bloggy/1.0.0 platform/1.0.0\")\n const parsedVersions = parseVersionHeader(clientVersionHeader);\n if (parsedVersions?.bloggyVersion) {\n bloggyVersion = parsedVersions.bloggyVersion;\n }\n }\n } catch (error) {\n console.warn(\"Failed to parse X-Bloggy-Version header:\", error);\n }\n }\n\n // Check compatibility between Bloggy core and platform versions\n // Only perform check if we have a valid Bloggy version (not \"unknown\")\n let compatibility: VersionCompatibilityResult = { compatible: true };\n\n if (bloggyVersion.version !== \"unknown\") {\n // Compare Bloggy core version with platform version\n // Both should follow semantic versioning\n compatibility = checkVersionCompatibility(bloggyVersion, platformVersion);\n }\n\n const response: VersionResponse = {\n success: true,\n versions: {\n bloggy: bloggyVersion,\n platform: platformVersion,\n },\n compatibility,\n };\n\n // Prepare response headers\n const rateLimitHeaders = getRateLimitHeaders(\n rateLimitCheck.rateLimitResult,\n );\n\n const responseHeaders = {\n \"X-Bloggy-Version\": `platform/${platformVersion.version}`,\n \"Cache-Control\": \"public, max-age=300, stale-while-revalidate=60\",\n ...rateLimitHeaders,\n };\n\n // Always return 200 OK with compatibility details in response body\n // The client should check compatibility.compatible field, not HTTP status\n return createCorsResponse(request, response, {\n status: 200,\n headers: responseHeaders,\n });\n } catch (error) {\n console.error(\"Version endpoint error:\", error);\n\n const errorResponse: VersionResponse = {\n success: false,\n versions: {\n bloggy: {\n name: \"unknown\",\n version: \"unknown\",\n major: 0,\n minor: 0,\n patch: 0,\n },\n platform: {\n name: \"unknown\",\n version: \"unknown\",\n major: 0,\n minor: 0,\n patch: 0,\n },\n },\n compatibility: {\n compatible: false,\n errorMessage:\n \"Internal server error while checking version compatibility\",\n },\n error: error instanceof Error ? error.message : \"Unknown error\",\n };\n\n return createCorsResponse(request, errorResponse, { status: 500 });\n }\n}\n\n/**\n * OPTIONS /api/blog/version\n *\n * Handle CORS preflight requests\n */\nexport async function OPTIONS(request: NextRequest): Promise<NextResponse> {\n return handleCorsOptions(request, [\"GET\"], {\n allowedHeaders: [\n \"Content-Type\",\n \"X-Bloggy-Version\",\n \"Authorization\",\n \"X-Requested-With\",\n ],\n });\n}\n","import { type NextRequest, NextResponse } from \"next/server\";\nimport { getStorage } from \"@/lib/database\";\nimport { getBlogPlatformVersion, parseVersionHeader } from \"@/lib/version\";\nimport {\n requireAuth,\n authenticateRequest,\n createTokenFingerprint,\n} from \"@/lib/auth\";\nimport { enforceRateLimit, getRateLimitHeaders } from \"@/lib/ratelimit\";\nimport { createCorsResponse, handleCorsOptions } from \"@/lib/cors\";\nimport { isValidSlug } from \"@/app/api/blog/publish/route\"; // Reuse slug validation from publish\n\n/**\n * GET /api/blog/slugs/{slug}\n *\n * Checks if a slug is already in use on the blog platform.\n * Used for dry-run validation in publishing workflow.\n *\n * Returns: { exists: boolean, message?: string }\n * - exists: false -> available\n * - exists: true -> taken, with suggestion message\n */\nexport async function GET(\n request: NextRequest,\n { params }: { params: Promise<{ slug: string }> },\n): Promise<NextResponse> {\n try {\n const { slug } = await params;\n // Authenticate (required for security)\n const auth = await authenticateRequest(request);\n if (!auth.authenticated) {\n const authCheck = await requireAuth(request);\n return NextResponse.json(authCheck.error!, { status: 401 });\n }\n\n // Rate limiting (same as publish: 5/min per token fingerprint)\n const tokenFingerprint = createTokenFingerprint(auth.token ?? \"anonymous\");\n const rateLimitCheck = await enforceRateLimit(tokenFingerprint);\n if (!rateLimitCheck.allowed) {\n const rateLimitData = (rateLimitCheck.errorResponse.error?.details\n ?.rateLimit as {\n limit: number;\n remaining: number;\n reset: number;\n count: number;\n success: boolean;\n }) || {\n limit: 10,\n remaining: 0,\n reset: Date.now() + 60000,\n count: 10,\n success: false,\n };\n\n const rateLimitHeaders = getRateLimitHeaders(rateLimitData);\n\n return createCorsResponse(request, rateLimitCheck.errorResponse, {\n status: 429,\n headers: rateLimitHeaders,\n });\n }\n\n // Extract slug from params\n if (!slug || !isValidSlug(slug)) {\n return createCorsResponse(\n request,\n {\n exists: false, // Treat invalid as non-existent, but error for clarity\n error: {\n code: \"PUB002\",\n message:\n \"Invalid slug format. Must be lowercase letters, numbers, and hyphens only.\",\n },\n },\n { status: 400 },\n );\n }\n\n // Version compatibility check\n const clientVersionHeader = request.headers.get(\"X-Bloggy-Version\");\n if (clientVersionHeader) {\n const parsedVersions = parseVersionHeader(clientVersionHeader);\n if (parsedVersions?.platformVersion) {\n const platformVersion = getBlogPlatformVersion();\n if (parsedVersions.platformVersion.major !== platformVersion.major) {\n return createCorsResponse(\n request,\n {\n exists: false,\n error: {\n code: \"PUB009\",\n message:\n \"Major version incompatibility. Please upgrade your blog platform package.\",\n details: {\n clientVersion: parsedVersions.platformVersion.version,\n serverVersion: platformVersion.version,\n },\n },\n },\n { status: 409 },\n );\n }\n }\n }\n\n // Check existence via storage\n const storage = getStorage();\n const existingArticle = await storage.getArticle(slug);\n const exists = existingArticle !== null;\n\n const responseBody = {\n exists,\n ...(exists && {\n message:\n \"Slug is already in use. Please choose another (e.g., append '-v2').\",\n }),\n };\n\n // Headers\n const platformVersion = getBlogPlatformVersion();\n const rateLimitHeaders = getRateLimitHeaders(\n rateLimitCheck.rateLimitResult,\n );\n const responseHeaders: Record<string, string> = {\n \"X-Bloggy-Version\": `platform/${platformVersion.version}`,\n ...rateLimitHeaders,\n };\n\n // Optional idempotency log (if provided)\n const idempotencyKey = request.headers.get(\"X-Idempotency-Key\");\n if (idempotencyKey) {\n responseHeaders[\"X-Idempotency-Key\"] = idempotencyKey;\n // Log for debugging\n console.log(\n `Slug check for idempotency: ${idempotencyKey}, exists: ${exists}`,\n );\n }\n\n return createCorsResponse(request, responseBody, {\n status: 200,\n headers: responseHeaders,\n });\n } catch (error: unknown) {\n console.error(\n \"Slug existence check error:\",\n error instanceof Error ? error.message : String(error),\n );\n\n return createCorsResponse(\n request,\n {\n exists: false,\n error: {\n code: \"PUB007\",\n message: \"Internal server error during slug check\",\n },\n },\n { status: 500 },\n );\n }\n}\n\n/**\n * OPTIONS /api/blog/slugs/{slug}\n * Handle CORS preflight\n */\nexport async function OPTIONS(request: NextRequest): Promise<NextResponse> {\n return handleCorsOptions(request, [\"GET\"]);\n}\n","/**\n * @xexr/blog-platform\n *\n * SEO-friendly blog platform for Next.js with Bloggy integration.\n * Enables publishing AI-generated content to custom domains.\n */\n\n// Re-export all public types\nexport * from \"./types\";\n\n// Component exports\nexport {\n default as BlogHomePage,\n generateBlogHomeMetadata,\n} from \"./app/blog/page\";\nexport {\n default as BlogArticlePage,\n generateArticleMetadata,\n} from \"./app/blog/[slug]/page\";\nexport {\n default as BlogAuthorPage,\n generateAuthorPageMetadata,\n} from \"./app/blog/authors/[slug]/page\";\nexport {\n default as Pagination,\n usePagination,\n generatePaginationMetadata,\n} from \"./components/Pagination\";\n\n// UI Component exports\nexport { Button, buttonVariants } from \"./components/ui/button\";\nexport {\n Card,\n CardHeader,\n CardTitle,\n CardDescription,\n CardContent,\n CardFooter,\n} from \"./components/ui/card\";\nexport {\n Pagination as ShadcnPagination,\n PaginationContent,\n PaginationItem,\n PaginationLink,\n PaginationNext,\n PaginationPrevious,\n PaginationEllipsis,\n} from \"./components/ui/pagination\";\n\n// Utility exports\nexport { cn } from \"./lib/utils\";\nexport {\n normalizeBlogBasePath,\n buildAuthorPath,\n buildBlogPath,\n getPathPrefixFromBlogUrl,\n} from \"./lib/urls\";\nexport {\n type AuthorArchive,\n type AuthorArchiveOptions,\n getAuthorArchive,\n getAuthorsFromArticles,\n loadAuthorArchive,\n} from \"./lib/authors\";\nexport {\n type BlogTheme,\n extractTableOfContents,\n formatArticleDateMeta,\n getBlogThemeStyle,\n} from \"./lib/article-ui\";\nexport {\n type TopicArchive,\n getAllTopics,\n getArticlePrimaryTopic,\n getTopicArchive,\n} from \"./lib/topics\";\nexport {\n BlogTopicArchivePage,\n BlogTopicsIndexPage,\n} from \"./components/TopicArchivePages\";\nexport { BlogAuthorsIndexPage } from \"./components/AuthorPages\";\nexport {\n NewsletterSignup,\n NEWSLETTER_SUCCESS_MESSAGE,\n type NewsletterSignupProps,\n} from \"./components/NewsletterSignup\";\n\n// Initialization exports\nexport {\n initBlogPlatform,\n initBlogPlatformDev,\n initBlogPlatformProd,\n initBlogPlatformOnce,\n type BlogPlatformConfig,\n} from \"./lib/init\";\n\n// Authentication exports\nexport {\n type AuthConfig,\n type AuthResult,\n ApiKeyAuth,\n EnvAuth,\n NoAuth,\n UninitializedAuth,\n createTokenFingerprint,\n extractTokenFromHeader,\n setAuthConfig,\n getAuthConfig,\n initEnvAuth,\n shouldSkipAuth,\n} from \"./lib/auth\";\n\n// Database exports\nexport {\n type BlogPlatformStorage,\n InMemoryStorage,\n getStorage,\n setStorage,\n} from \"./lib/database\";\n\n// Drizzle storage adapter exports\nexport {\n DrizzleStorage,\n bpArticles,\n bpOperations,\n getDrizzleAdapterSql,\n} from \"./lib/storage/drizzle\";\n\n// Rate limiting exports\nexport {\n type RateLimitConfig,\n type RateLimitResult,\n configureRateLimit,\n autoConfigureRateLimit,\n checkRateLimit,\n enforceRateLimit,\n getRateLimitHeaders,\n createRateLimitErrorResponse,\n} from \"./lib/ratelimit\";\n\n// SEO utility exports\nexport {\n type CanonicalUrlOptions,\n normalizeDomain,\n normalizeSlug,\n generateCanonicalUrl,\n generateCanonicalUrlFromSlug,\n isValidCanonicalUrl,\n getBaseUrl,\n updateArticleCanonicalUrl,\n} from \"./lib/seo\";\n\n// Metadata utility exports\nexport {\n type MetadataOptions,\n type GeneratedMetadata,\n type MetaTag,\n type LinkTag,\n generateSiteMetadata,\n metadataToHtml,\n validateMetadata,\n} from \"./lib/metadata\";\n\n// Sitemap utility exports\nexport {\n type SitemapOptions,\n type SitemapChangeFreq,\n type NextjsSitemapEntry,\n type BlogSitemapConfig,\n generateBlogSitemapEntries,\n createBlogSitemapRoute,\n createDynamicBlogSitemap,\n // Legacy exports (deprecated)\n type SitemapEntry,\n type SitemapData,\n generateSitemap,\n sitemapToXml,\n generateSitemapIndex,\n validateSitemap,\n} from \"./lib/sitemap\";\n\n// Structured data utility exports\nexport {\n type PersonSchema,\n type OrganizationSchema,\n type BlogPostingSchema,\n type WebSiteSchema,\n type BreadcrumbListSchema,\n type StructuredDataOptions,\n generateArticleStructuredData,\n generateAuthorStructuredData,\n generateOrganizationStructuredData,\n generateWebSiteStructuredData,\n generateBreadcrumbStructuredData,\n generateCompleteArticleStructuredData,\n generateBlogHomeStructuredData,\n validateStructuredData,\n structuredDataToJsonLd,\n createStructuredDataScript,\n extractKeywordsFromArticle,\n safeGenerateArticleStructuredData,\n StructuredDataError,\n} from \"./lib/structured-data\";\n\n// API Route handlers\nexport { POST as publishHandler } from \"./app/api/blog/publish/route\";\nexport { POST as unpublishHandler } from \"./app/api/blog/unpublish/route\";\nexport { GET as versionHandler } from \"./app/api/blog/version/route\";\nexport {\n GET as slugExistsHandler,\n OPTIONS as slugExistsOptionsHandler,\n} from \"./app/api/blog/slugs/[slug]/route\";\n\n// Version information\n// Export package version (imported from package.json at build time)\nimport packageJson from \"../package.json\";\nexport const PACKAGE_VERSION = packageJson.version;\n"]}