@xexr/blog-platform 1.0.1 → 1.0.2

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.
@@ -18,6 +18,8 @@ import {
18
18
  generateCompleteArticleStructuredData,
19
19
  createStructuredDataScript,
20
20
  } from "../../../lib/structured-data";
21
+ import { articleMdxOptions } from "../../../lib/mdx";
22
+ import { buildBlogPath, normalizeBlogBasePath } from "../../../lib/urls";
21
23
 
22
24
  interface ArticlePageProps {
23
25
  article: PublishedArticle;
@@ -37,6 +39,8 @@ interface ArticlePageProps {
37
39
  title: string;
38
40
  };
39
41
  };
42
+ /** Public path where this blog is mounted, e.g. "/blog" or "/new-blog". */
43
+ basePath?: string;
40
44
  }
41
45
 
42
46
  /**
@@ -58,7 +62,9 @@ export default function ArticlePage({
58
62
  article,
59
63
  className,
60
64
  navigation,
65
+ basePath = "/blog",
61
66
  }: ArticlePageProps) {
67
+ const normalizedBasePath = normalizeBlogBasePath(basePath) || "/";
62
68
  const publishedDate = new Date(article.publishedAt);
63
69
  const updatedDate = new Date(article.updatedAt);
64
70
  const isUpdated = updatedDate.getTime() !== publishedDate.getTime();
@@ -173,7 +179,7 @@ export default function ArticlePage({
173
179
  {/* Article Content */}
174
180
  <div className="article-content">
175
181
  <div 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-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-img:mx-auto prose-img:rounded-lg prose-a:transition-colors max-w-none">
176
- <MDXRemote source={article.content} />
182
+ <MDXRemote source={article.content} options={articleMdxOptions} />
177
183
  </div>
178
184
  </div>
179
185
 
@@ -247,7 +253,9 @@ export default function ArticlePage({
247
253
  {/* JSON-LD Structured Data */}
248
254
  {(() => {
249
255
  const structuredDataProps = createStructuredDataScript(
250
- generateCompleteArticleStructuredData(article),
256
+ generateCompleteArticleStructuredData(article, {
257
+ pathPrefix: normalizedBasePath,
258
+ }),
251
259
  );
252
260
  return (
253
261
  <script
@@ -266,11 +274,15 @@ export default function ArticlePage({
266
274
  * Generate metadata for the article page for SEO optimization.
267
275
  * This function should be used in the Next.js metadata API.
268
276
  */
269
- export function generateArticleMetadata(article: PublishedArticle) {
277
+ export function generateArticleMetadata(
278
+ article: PublishedArticle,
279
+ basePath = "/blog",
280
+ ) {
270
281
  const title = article.meta.title ?? article.title;
271
282
  const description = article.meta.description ?? article.excerpt;
272
283
  const canonicalUrl =
273
- article.meta.canonicalUrl ?? `${article.site.domain}/blog/${article.slug}`;
284
+ article.meta.canonicalUrl ??
285
+ `${article.site.domain}${buildBlogPath(basePath, article.slug)}`;
274
286
  const ogImage = article.meta.ogImage ?? article.featuredImage;
275
287
 
276
288
  return {
@@ -11,6 +11,7 @@ import {
11
11
  generateBlogHomeStructuredData,
12
12
  createStructuredDataScript,
13
13
  } from "../../lib/structured-data";
14
+ import { buildBlogPath, normalizeBlogBasePath } from "../../lib/urls";
14
15
  import { formatDistanceToNow } from "date-fns";
15
16
 
16
17
  interface BlogHomePageProps {
@@ -22,6 +23,8 @@ interface BlogHomePageProps {
22
23
  site?: PublishedSite;
23
24
  /** Whether to include structured data */
24
25
  includeStructuredData?: boolean;
26
+ /** Public path where this blog is mounted, e.g. "/blog" or "/new-blog". */
27
+ basePath?: string;
25
28
  /** Pagination configuration */
26
29
  pagination?: {
27
30
  currentPage: number;
@@ -44,8 +47,11 @@ export default function BlogHomePage({
44
47
  className,
45
48
  site,
46
49
  includeStructuredData = false,
50
+ basePath = "/blog",
47
51
  pagination,
48
52
  }: BlogHomePageProps) {
53
+ const normalizedBasePath = normalizeBlogBasePath(basePath) || "/";
54
+
49
55
  return (
50
56
  <div
51
57
  className={cn(
@@ -81,7 +87,11 @@ export default function BlogHomePage({
81
87
  ) : (
82
88
  <div className="space-y-0">
83
89
  {articles.map((article) => (
84
- <ArticlePreview key={article.id} article={article} />
90
+ <ArticlePreview
91
+ key={article.id}
92
+ article={article}
93
+ basePath={normalizedBasePath}
94
+ />
85
95
  ))}
86
96
  </div>
87
97
  )}
@@ -92,7 +102,7 @@ export default function BlogHomePage({
92
102
  <Pagination
93
103
  currentPage={pagination.currentPage}
94
104
  totalPages={pagination.totalPages}
95
- baseUrl={pagination.baseUrl ?? "/blog"}
105
+ baseUrl={pagination.baseUrl ?? normalizedBasePath}
96
106
  className="justify-center"
97
107
  />
98
108
  </div>
@@ -104,7 +114,9 @@ export default function BlogHomePage({
104
114
  site &&
105
115
  (() => {
106
116
  const structuredDataProps = createStructuredDataScript(
107
- generateBlogHomeStructuredData(site, articles.slice(0, 5)),
117
+ generateBlogHomeStructuredData(site, articles.slice(0, 5), {
118
+ pathPrefix: normalizedBasePath,
119
+ }),
108
120
  );
109
121
  return (
110
122
  <script
@@ -130,8 +142,14 @@ function formatReadingTime(seconds: number): string {
130
142
  /**
131
143
  * Individual article preview component for the blog listing.
132
144
  */
133
- function ArticlePreview({ article }: { article: PublishedArticle }) {
134
- const articleUrl = `/blog/${article.slug}`;
145
+ function ArticlePreview({
146
+ article,
147
+ basePath,
148
+ }: {
149
+ article: PublishedArticle;
150
+ basePath: string;
151
+ }) {
152
+ const articleUrl = buildBlogPath(basePath, article.slug);
135
153
  const formattedDate = formatDistanceToNow(new Date(article.publishedAt), {
136
154
  addSuffix: true,
137
155
  });
@@ -169,7 +187,7 @@ function ArticlePreview({ article }: { article: PublishedArticle }) {
169
187
  {article.title}
170
188
  </h2>
171
189
 
172
- <div className="flex flex-wrap items-center gap-x-3 gap-y-1 text-sm text-muted-foreground">
190
+ <div className="text-muted-foreground flex flex-wrap items-center gap-x-3 gap-y-1 text-sm">
173
191
  {article.author && (
174
192
  <>
175
193
  <span className="font-medium">{article.author.name}</span>
@@ -225,7 +243,7 @@ function ArticlePreview({ article }: { article: PublishedArticle }) {
225
243
  )}
226
244
  </div>
227
245
 
228
- <div className="flex flex-wrap items-center gap-x-3 gap-y-1 text-sm text-muted-foreground">
246
+ <div className="text-muted-foreground flex flex-wrap items-center gap-x-3 gap-y-1 text-sm">
229
247
  {article.author && (
230
248
  <>
231
249
  <span className="font-medium">{article.author.name}</span>
@@ -261,6 +279,7 @@ export function generateBlogHomeMetadata(
261
279
  currentPage: number;
262
280
  totalPages: number;
263
281
  },
282
+ basePath = "/blog",
264
283
  ) {
265
284
  const baseTitle = siteName ? `${siteName} - Blog` : "Blog";
266
285
  const title =
@@ -272,7 +291,7 @@ export function generateBlogHomeMetadata(
272
291
  siteDescription ?? "Read our latest articles and insights.";
273
292
 
274
293
  // Generate pagination URLs for SEO
275
- const baseUrl = "/blog";
294
+ const baseUrl = normalizeBlogBasePath(basePath) || "/";
276
295
  const canonicalUrl = siteUrl
277
296
  ? `${siteUrl}${pagination && pagination.currentPage > 1 ? `${baseUrl}?page=${pagination.currentPage}` : baseUrl}`
278
297
  : undefined;
package/dist/index.d.mts CHANGED
@@ -18,6 +18,8 @@ interface BlogHomePageProps {
18
18
  site?: PublishedSite;
19
19
  /** Whether to include structured data */
20
20
  includeStructuredData?: boolean;
21
+ /** Public path where this blog is mounted, e.g. "/blog" or "/new-blog". */
22
+ basePath?: string;
21
23
  /** Pagination configuration */
22
24
  pagination?: {
23
25
  currentPage: number;
@@ -32,7 +34,7 @@ interface BlogHomePageProps {
32
34
  * @xexr/blog-platform package. It provides a clean, SEO-friendly
33
35
  * article listing with proper metadata.
34
36
  */
35
- declare function BlogHomePage({ articles, siteName, siteTagline, className, site, includeStructuredData, pagination, }: BlogHomePageProps): react_jsx_runtime.JSX.Element;
37
+ declare function BlogHomePage({ articles, siteName, siteTagline, className, site, includeStructuredData, basePath, pagination, }: BlogHomePageProps): react_jsx_runtime.JSX.Element;
36
38
  /**
37
39
  * Generate metadata for the blog home page for SEO optimization.
38
40
  * This function should be used in the Next.js metadata API.
@@ -40,7 +42,7 @@ declare function BlogHomePage({ articles, siteName, siteTagline, className, site
40
42
  declare function generateBlogHomeMetadata(siteName?: string, siteDescription?: string, siteUrl?: string, pagination?: {
41
43
  currentPage: number;
42
44
  totalPages: number;
43
- }): {
45
+ }, basePath?: string): {
44
46
  title: string;
45
47
  description: string;
46
48
  openGraph: {
@@ -81,13 +83,15 @@ interface ArticlePageProps {
81
83
  title: string;
82
84
  };
83
85
  };
86
+ /** Public path where this blog is mounted, e.g. "/blog" or "/new-blog". */
87
+ basePath?: string;
84
88
  }
85
- declare function ArticlePage({ article, className, navigation, }: ArticlePageProps): react_jsx_runtime.JSX.Element;
89
+ declare function ArticlePage({ article, className, navigation, basePath, }: ArticlePageProps): react_jsx_runtime.JSX.Element;
86
90
  /**
87
91
  * Generate metadata for the article page for SEO optimization.
88
92
  * This function should be used in the Next.js metadata API.
89
93
  */
90
- declare function generateArticleMetadata(article: PublishedArticle): {
94
+ declare function generateArticleMetadata(article: PublishedArticle, basePath?: string): {
91
95
  title: string;
92
96
  description: string;
93
97
  keywords: string;
@@ -202,6 +206,13 @@ declare function PaginationEllipsis({ className, ...props }: React.ComponentProp
202
206
 
203
207
  declare function cn(...inputs: ClassValue[]): string;
204
208
 
209
+ /**
210
+ * URL helpers shared by package UI, metadata, and sitemap integrations.
211
+ */
212
+ declare function normalizeBlogBasePath(basePath?: string): string;
213
+ declare function buildBlogPath(basePath: string | undefined, slug?: string): string;
214
+ declare function getPathPrefixFromBlogUrl(blogUrl: string): string;
215
+
205
216
  /**
206
217
  * Authentication configuration interface
207
218
  * Customers can implement this to customize authentication behavior
@@ -1796,4 +1807,4 @@ declare function OPTIONS(request: NextRequest): Promise<NextResponse>;
1796
1807
 
1797
1808
  declare const PACKAGE_VERSION: string;
1798
1809
 
1799
- export { ApiKeyAuth, type AuthConfig, type AuthResult, ArticlePage as BlogArticlePage, BlogHomePage, type BlogPlatformConfig, type BlogPlatformStorage, type BlogPostingSchema, type BlogSitemapConfig, type BreadcrumbListSchema, Button, type CanonicalUrlOptions, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, DrizzleStorage, EnvAuth, type GeneratedMetadata, InMemoryStorage, type LinkTag, type MetaTag, type MetadataOptions, type NextjsSitemapEntry, NoAuth, type OrganizationSchema, PACKAGE_VERSION, Pagination$1 as Pagination, PaginationContent, PaginationEllipsis, PaginationItem, PaginationLink, PaginationNext, PaginationPrevious, type PersonSchema, PublishResult, PublishedArticle, PublishedAuthor, PublishedSite, type RateLimitConfig, type RateLimitResult, Pagination as ShadcnPagination, type SitemapChangeFreq, type SitemapData, type SitemapEntry, type SitemapOptions, StructuredDataError, type StructuredDataOptions, UninitializedAuth, type WebSiteSchema, autoConfigureRateLimit, bpArticles, bpOperations, buttonVariants, checkRateLimit, cn, configureRateLimit, createBlogSitemapRoute, createDynamicBlogSitemap, createRateLimitErrorResponse, createStructuredDataScript, enforceRateLimit, extractKeywordsFromArticle, extractTokenFromHeader, generateArticleMetadata, generateArticleStructuredData, generateAuthorStructuredData, generateBlogHomeMetadata, generateBlogHomeStructuredData, generateBlogSitemapEntries, generateBreadcrumbStructuredData, generateCanonicalUrl, generateCanonicalUrlFromSlug, generateCompleteArticleStructuredData, generateOrganizationStructuredData, generatePaginationMetadata, generateSiteMetadata, generateSitemap, generateSitemapIndex, generateWebSiteStructuredData, getAuthConfig, getBaseUrl, getDrizzleAdapterSql, getRateLimitHeaders, getStorage, initBlogPlatform, initBlogPlatformDev, initBlogPlatformOnce, initBlogPlatformProd, initEnvAuth, isValidCanonicalUrl, metadataToHtml, normalizeDomain, normalizeSlug, POST$1 as publishHandler, safeGenerateArticleStructuredData, setAuthConfig, setStorage, shouldSkipAuth, sitemapToXml, GET as slugExistsHandler, OPTIONS as slugExistsOptionsHandler, structuredDataToJsonLd, POST as unpublishHandler, updateArticleCanonicalUrl, usePagination, validateMetadata, validateSitemap, validateStructuredData, GET$1 as versionHandler };
1810
+ export { ApiKeyAuth, type AuthConfig, type AuthResult, ArticlePage as BlogArticlePage, BlogHomePage, type BlogPlatformConfig, type BlogPlatformStorage, type BlogPostingSchema, type BlogSitemapConfig, type BreadcrumbListSchema, Button, type CanonicalUrlOptions, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, DrizzleStorage, EnvAuth, type GeneratedMetadata, InMemoryStorage, type LinkTag, type MetaTag, type MetadataOptions, type NextjsSitemapEntry, NoAuth, type OrganizationSchema, PACKAGE_VERSION, Pagination$1 as Pagination, PaginationContent, PaginationEllipsis, PaginationItem, PaginationLink, PaginationNext, PaginationPrevious, type PersonSchema, PublishResult, PublishedArticle, PublishedAuthor, PublishedSite, type RateLimitConfig, type RateLimitResult, Pagination as ShadcnPagination, type SitemapChangeFreq, type SitemapData, type SitemapEntry, type SitemapOptions, StructuredDataError, type StructuredDataOptions, UninitializedAuth, type WebSiteSchema, autoConfigureRateLimit, bpArticles, bpOperations, buildBlogPath, buttonVariants, checkRateLimit, cn, configureRateLimit, createBlogSitemapRoute, createDynamicBlogSitemap, createRateLimitErrorResponse, createStructuredDataScript, enforceRateLimit, extractKeywordsFromArticle, extractTokenFromHeader, generateArticleMetadata, generateArticleStructuredData, generateAuthorStructuredData, generateBlogHomeMetadata, generateBlogHomeStructuredData, generateBlogSitemapEntries, generateBreadcrumbStructuredData, generateCanonicalUrl, generateCanonicalUrlFromSlug, generateCompleteArticleStructuredData, generateOrganizationStructuredData, generatePaginationMetadata, generateSiteMetadata, generateSitemap, generateSitemapIndex, generateWebSiteStructuredData, getAuthConfig, getBaseUrl, getDrizzleAdapterSql, getPathPrefixFromBlogUrl, getRateLimitHeaders, getStorage, initBlogPlatform, initBlogPlatformDev, initBlogPlatformOnce, initBlogPlatformProd, initEnvAuth, isValidCanonicalUrl, metadataToHtml, normalizeBlogBasePath, normalizeDomain, normalizeSlug, POST$1 as publishHandler, safeGenerateArticleStructuredData, setAuthConfig, setStorage, shouldSkipAuth, sitemapToXml, GET as slugExistsHandler, OPTIONS as slugExistsOptionsHandler, structuredDataToJsonLd, POST as unpublishHandler, updateArticleCanonicalUrl, usePagination, validateMetadata, validateSitemap, validateStructuredData, GET$1 as versionHandler };
package/dist/index.d.ts CHANGED
@@ -18,6 +18,8 @@ interface BlogHomePageProps {
18
18
  site?: PublishedSite;
19
19
  /** Whether to include structured data */
20
20
  includeStructuredData?: boolean;
21
+ /** Public path where this blog is mounted, e.g. "/blog" or "/new-blog". */
22
+ basePath?: string;
21
23
  /** Pagination configuration */
22
24
  pagination?: {
23
25
  currentPage: number;
@@ -32,7 +34,7 @@ interface BlogHomePageProps {
32
34
  * @xexr/blog-platform package. It provides a clean, SEO-friendly
33
35
  * article listing with proper metadata.
34
36
  */
35
- declare function BlogHomePage({ articles, siteName, siteTagline, className, site, includeStructuredData, pagination, }: BlogHomePageProps): react_jsx_runtime.JSX.Element;
37
+ declare function BlogHomePage({ articles, siteName, siteTagline, className, site, includeStructuredData, basePath, pagination, }: BlogHomePageProps): react_jsx_runtime.JSX.Element;
36
38
  /**
37
39
  * Generate metadata for the blog home page for SEO optimization.
38
40
  * This function should be used in the Next.js metadata API.
@@ -40,7 +42,7 @@ declare function BlogHomePage({ articles, siteName, siteTagline, className, site
40
42
  declare function generateBlogHomeMetadata(siteName?: string, siteDescription?: string, siteUrl?: string, pagination?: {
41
43
  currentPage: number;
42
44
  totalPages: number;
43
- }): {
45
+ }, basePath?: string): {
44
46
  title: string;
45
47
  description: string;
46
48
  openGraph: {
@@ -81,13 +83,15 @@ interface ArticlePageProps {
81
83
  title: string;
82
84
  };
83
85
  };
86
+ /** Public path where this blog is mounted, e.g. "/blog" or "/new-blog". */
87
+ basePath?: string;
84
88
  }
85
- declare function ArticlePage({ article, className, navigation, }: ArticlePageProps): react_jsx_runtime.JSX.Element;
89
+ declare function ArticlePage({ article, className, navigation, basePath, }: ArticlePageProps): react_jsx_runtime.JSX.Element;
86
90
  /**
87
91
  * Generate metadata for the article page for SEO optimization.
88
92
  * This function should be used in the Next.js metadata API.
89
93
  */
90
- declare function generateArticleMetadata(article: PublishedArticle): {
94
+ declare function generateArticleMetadata(article: PublishedArticle, basePath?: string): {
91
95
  title: string;
92
96
  description: string;
93
97
  keywords: string;
@@ -202,6 +206,13 @@ declare function PaginationEllipsis({ className, ...props }: React.ComponentProp
202
206
 
203
207
  declare function cn(...inputs: ClassValue[]): string;
204
208
 
209
+ /**
210
+ * URL helpers shared by package UI, metadata, and sitemap integrations.
211
+ */
212
+ declare function normalizeBlogBasePath(basePath?: string): string;
213
+ declare function buildBlogPath(basePath: string | undefined, slug?: string): string;
214
+ declare function getPathPrefixFromBlogUrl(blogUrl: string): string;
215
+
205
216
  /**
206
217
  * Authentication configuration interface
207
218
  * Customers can implement this to customize authentication behavior
@@ -1796,4 +1807,4 @@ declare function OPTIONS(request: NextRequest): Promise<NextResponse>;
1796
1807
 
1797
1808
  declare const PACKAGE_VERSION: string;
1798
1809
 
1799
- export { ApiKeyAuth, type AuthConfig, type AuthResult, ArticlePage as BlogArticlePage, BlogHomePage, type BlogPlatformConfig, type BlogPlatformStorage, type BlogPostingSchema, type BlogSitemapConfig, type BreadcrumbListSchema, Button, type CanonicalUrlOptions, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, DrizzleStorage, EnvAuth, type GeneratedMetadata, InMemoryStorage, type LinkTag, type MetaTag, type MetadataOptions, type NextjsSitemapEntry, NoAuth, type OrganizationSchema, PACKAGE_VERSION, Pagination$1 as Pagination, PaginationContent, PaginationEllipsis, PaginationItem, PaginationLink, PaginationNext, PaginationPrevious, type PersonSchema, PublishResult, PublishedArticle, PublishedAuthor, PublishedSite, type RateLimitConfig, type RateLimitResult, Pagination as ShadcnPagination, type SitemapChangeFreq, type SitemapData, type SitemapEntry, type SitemapOptions, StructuredDataError, type StructuredDataOptions, UninitializedAuth, type WebSiteSchema, autoConfigureRateLimit, bpArticles, bpOperations, buttonVariants, checkRateLimit, cn, configureRateLimit, createBlogSitemapRoute, createDynamicBlogSitemap, createRateLimitErrorResponse, createStructuredDataScript, enforceRateLimit, extractKeywordsFromArticle, extractTokenFromHeader, generateArticleMetadata, generateArticleStructuredData, generateAuthorStructuredData, generateBlogHomeMetadata, generateBlogHomeStructuredData, generateBlogSitemapEntries, generateBreadcrumbStructuredData, generateCanonicalUrl, generateCanonicalUrlFromSlug, generateCompleteArticleStructuredData, generateOrganizationStructuredData, generatePaginationMetadata, generateSiteMetadata, generateSitemap, generateSitemapIndex, generateWebSiteStructuredData, getAuthConfig, getBaseUrl, getDrizzleAdapterSql, getRateLimitHeaders, getStorage, initBlogPlatform, initBlogPlatformDev, initBlogPlatformOnce, initBlogPlatformProd, initEnvAuth, isValidCanonicalUrl, metadataToHtml, normalizeDomain, normalizeSlug, POST$1 as publishHandler, safeGenerateArticleStructuredData, setAuthConfig, setStorage, shouldSkipAuth, sitemapToXml, GET as slugExistsHandler, OPTIONS as slugExistsOptionsHandler, structuredDataToJsonLd, POST as unpublishHandler, updateArticleCanonicalUrl, usePagination, validateMetadata, validateSitemap, validateStructuredData, GET$1 as versionHandler };
1810
+ export { ApiKeyAuth, type AuthConfig, type AuthResult, ArticlePage as BlogArticlePage, BlogHomePage, type BlogPlatformConfig, type BlogPlatformStorage, type BlogPostingSchema, type BlogSitemapConfig, type BreadcrumbListSchema, Button, type CanonicalUrlOptions, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, DrizzleStorage, EnvAuth, type GeneratedMetadata, InMemoryStorage, type LinkTag, type MetaTag, type MetadataOptions, type NextjsSitemapEntry, NoAuth, type OrganizationSchema, PACKAGE_VERSION, Pagination$1 as Pagination, PaginationContent, PaginationEllipsis, PaginationItem, PaginationLink, PaginationNext, PaginationPrevious, type PersonSchema, PublishResult, PublishedArticle, PublishedAuthor, PublishedSite, type RateLimitConfig, type RateLimitResult, Pagination as ShadcnPagination, type SitemapChangeFreq, type SitemapData, type SitemapEntry, type SitemapOptions, StructuredDataError, type StructuredDataOptions, UninitializedAuth, type WebSiteSchema, autoConfigureRateLimit, bpArticles, bpOperations, buildBlogPath, buttonVariants, checkRateLimit, cn, configureRateLimit, createBlogSitemapRoute, createDynamicBlogSitemap, createRateLimitErrorResponse, createStructuredDataScript, enforceRateLimit, extractKeywordsFromArticle, extractTokenFromHeader, generateArticleMetadata, generateArticleStructuredData, generateAuthorStructuredData, generateBlogHomeMetadata, generateBlogHomeStructuredData, generateBlogSitemapEntries, generateBreadcrumbStructuredData, generateCanonicalUrl, generateCanonicalUrlFromSlug, generateCompleteArticleStructuredData, generateOrganizationStructuredData, generatePaginationMetadata, generateSiteMetadata, generateSitemap, generateSitemapIndex, generateWebSiteStructuredData, getAuthConfig, getBaseUrl, getDrizzleAdapterSql, getPathPrefixFromBlogUrl, getRateLimitHeaders, getStorage, initBlogPlatform, initBlogPlatformDev, initBlogPlatformOnce, initBlogPlatformProd, initEnvAuth, isValidCanonicalUrl, metadataToHtml, normalizeBlogBasePath, normalizeDomain, normalizeSlug, POST$1 as publishHandler, safeGenerateArticleStructuredData, setAuthConfig, setStorage, shouldSkipAuth, sitemapToXml, GET as slugExistsHandler, OPTIONS as slugExistsOptionsHandler, structuredDataToJsonLd, POST as unpublishHandler, updateArticleCanonicalUrl, usePagination, validateMetadata, validateSitemap, validateStructuredData, GET$1 as versionHandler };