@sonordev/site-kit 5.8.2 → 6.0.0
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.
- package/README.md +11 -11
- package/agent-manifest.json +22 -11
- package/dist/{AnalyticsProvider-LUEUDZZC.mjs → AnalyticsProvider-6QVM2B6O.mjs} +6 -6
- package/dist/{AnalyticsProvider-LUEUDZZC.mjs.map → AnalyticsProvider-6QVM2B6O.mjs.map} +1 -1
- package/dist/{AnalyticsProvider-4JV3OFCG.js → AnalyticsProvider-AZQXLRWN.js} +10 -10
- package/dist/{AnalyticsProvider-4JV3OFCG.js.map → AnalyticsProvider-AZQXLRWN.js.map} +1 -1
- package/dist/ArticleFaqSection-3KZ24MFS.js +13 -0
- package/dist/ArticleFaqSection-3KZ24MFS.js.map +1 -0
- package/dist/ArticleFaqSection-XZPXJVH4.mjs +11 -0
- package/dist/ArticleFaqSection-XZPXJVH4.mjs.map +1 -0
- package/dist/{BlogViewTracker-YQMTEGYZ.mjs → ArticleViewTracker-AEWJMXQQ.mjs} +13 -13
- package/dist/ArticleViewTracker-AEWJMXQQ.mjs.map +1 -0
- package/dist/{BlogViewTracker-32C4SCHA.js → ArticleViewTracker-CFBTQ46B.js} +16 -16
- package/dist/ArticleViewTracker-CFBTQ46B.js.map +1 -0
- package/dist/ChatWidget-6626OPXO.mjs +15 -0
- package/dist/{ChatWidget-IRTAMRQS.mjs.map → ChatWidget-6626OPXO.mjs.map} +1 -1
- package/dist/ChatWidget-U24AYLXF.js +24 -0
- package/dist/{ChatWidget-KCXQXNUF.js.map → ChatWidget-U24AYLXF.js.map} +1 -1
- package/dist/EngageWidget-TR47W2ZI.mjs +12 -0
- package/dist/{EngageWidget-7AIUJRXV.mjs.map → EngageWidget-TR47W2ZI.mjs.map} +1 -1
- package/dist/EngageWidget-XUTDFRF3.js +21 -0
- package/dist/{EngageWidget-EUUZHQOU.js.map → EngageWidget-XUTDFRF3.js.map} +1 -1
- package/dist/{FileField-XJYJO5HE.mjs → FileField-DNNC5IPS.mjs} +5 -5
- package/dist/{FileField-XJYJO5HE.mjs.map → FileField-DNNC5IPS.mjs.map} +1 -1
- package/dist/{FileField-SNI5XCHQ.js → FileField-R4RQG77G.js} +6 -6
- package/dist/{FileField-SNI5XCHQ.js.map → FileField-R4RQG77G.js.map} +1 -1
- package/dist/{FormSpotlight-S64G4CMM.js → FormSpotlight-7ILRAD3W.js} +9 -9
- package/dist/{FormSpotlight-S64G4CMM.js.map → FormSpotlight-7ILRAD3W.js.map} +1 -1
- package/dist/{FormSpotlight-BCXI4A4R.mjs → FormSpotlight-MXY4I46H.mjs} +3 -3
- package/dist/{FormSpotlight-BCXI4A4R.mjs.map → FormSpotlight-MXY4I46H.mjs.map} +1 -1
- package/dist/{FormStage-PX5TVY25.js → FormStage-CVD3I3SE.js} +9 -9
- package/dist/{FormStage-PX5TVY25.js.map → FormStage-CVD3I3SE.js.map} +1 -1
- package/dist/{FormStage-RHARCSPS.mjs → FormStage-FDJGRGEU.mjs} +3 -3
- package/dist/{FormStage-RHARCSPS.mjs.map → FormStage-FDJGRGEU.mjs.map} +1 -1
- package/dist/ManagedForm-5675CLWS.mjs +16 -0
- package/dist/{ManagedForm-7IDXBQS6.mjs.map → ManagedForm-5675CLWS.mjs.map} +1 -1
- package/dist/ManagedForm-KYIK54SL.js +25 -0
- package/dist/{ManagedForm-RI2TSUZD.js.map → ManagedForm-KYIK54SL.js.map} +1 -1
- package/dist/{ManagedNewsletterForm-UXBJ5OJB.mjs → ManagedNewsletterForm-DFLDGNQU.mjs} +11 -11
- package/dist/ManagedNewsletterForm-DFLDGNQU.mjs.map +1 -0
- package/dist/{ManagedNewsletterForm-IAGIHBNT.js → ManagedNewsletterForm-IH3MRJOD.js} +13 -13
- package/dist/ManagedNewsletterForm-IH3MRJOD.js.map +1 -0
- package/dist/{SignalCore-Q2BQMPCJ.js → SignalCore-6LYIZFXK.js} +11 -11
- package/dist/{SignalCore-Q2BQMPCJ.js.map → SignalCore-6LYIZFXK.js.map} +1 -1
- package/dist/{SignalCore-37WGILFY.mjs → SignalCore-ZH3R6XD3.mjs} +5 -5
- package/dist/{SignalCore-37WGILFY.mjs.map → SignalCore-ZH3R6XD3.mjs.map} +1 -1
- package/dist/SitemapSync-PKBXWVI6.mjs +9 -0
- package/dist/{SitemapSync-YIAI7PMT.mjs.map → SitemapSync-PKBXWVI6.mjs.map} +1 -1
- package/dist/SitemapSync-PZ76V5MX.js +18 -0
- package/dist/{SitemapSync-DWEL7HTB.js.map → SitemapSync-PZ76V5MX.js.map} +1 -1
- package/dist/analytics/index.js +9 -9
- package/dist/analytics/index.mjs +4 -4
- package/dist/{blog-styles-7AKRUMV7.mjs → article-styles-DACUAOVT.mjs} +124 -124
- package/dist/article-styles-DACUAOVT.mjs.map +1 -0
- package/dist/{blog-styles-6EY3BS5Y.js → article-styles-JHHTNHOK.js} +125 -125
- package/dist/article-styles-JHHTNHOK.js.map +1 -0
- package/dist/article-tables-EWXG4LNP.js +17 -0
- package/dist/article-tables-EWXG4LNP.js.map +1 -0
- package/dist/article-tables-OGE52LNT.mjs +4 -0
- package/dist/article-tables-OGE52LNT.mjs.map +1 -0
- package/dist/{blog/BlogPost.d.ts → articles/Article.d.ts} +18 -16
- package/dist/articles/Article.d.ts.map +1 -0
- package/dist/{blog/BlogFAQ.d.ts → articles/ArticleFAQ.d.ts} +6 -6
- package/dist/articles/ArticleFAQ.d.ts.map +1 -0
- package/dist/articles/ArticleFaqSection.d.ts +3 -0
- package/dist/articles/ArticleFaqSection.d.ts.map +1 -0
- package/dist/{blog/BlogList.d.ts → articles/ArticleList.d.ts} +16 -16
- package/dist/articles/ArticleList.d.ts.map +1 -0
- package/dist/{blog/BlogViewTracker.d.ts → articles/ArticleViewTracker.d.ts} +4 -4
- package/dist/articles/ArticleViewTracker.d.ts.map +1 -0
- package/dist/{blog → articles}/AuthorCard.d.ts +3 -3
- package/dist/articles/AuthorCard.d.ts.map +1 -0
- package/dist/{blog → articles}/AuthorPage.d.ts +1 -1
- package/dist/articles/AuthorPage.d.ts.map +1 -0
- package/dist/{blog → articles}/ClusterLandingPage.d.ts +6 -6
- package/dist/articles/ClusterLandingPage.d.ts.map +1 -0
- package/dist/{blog → articles}/ClusterNavigation.d.ts +5 -5
- package/dist/articles/ClusterNavigation.d.ts.map +1 -0
- package/dist/{blog → articles}/ManagedNewsletterForm.d.ts +1 -1
- package/dist/articles/ManagedNewsletterForm.d.ts.map +1 -0
- package/dist/{blog → articles}/NewsletterShell.d.ts +1 -1
- package/dist/articles/NewsletterShell.d.ts.map +1 -0
- package/dist/{blog → articles}/NewsletterWidget.d.ts +4 -4
- package/dist/articles/NewsletterWidget.d.ts.map +1 -0
- package/dist/{blog/BlogLayout.d.ts → articles/PublicationLayout.d.ts} +18 -18
- package/dist/articles/PublicationLayout.d.ts.map +1 -0
- package/dist/{blog/BlogSidebar.d.ts → articles/PublicationSidebar.d.ts} +8 -8
- package/dist/articles/PublicationSidebar.d.ts.map +1 -0
- package/dist/{blog → articles}/RelatedPosts.d.ts +6 -6
- package/dist/articles/RelatedPosts.d.ts.map +1 -0
- package/dist/{blog → articles}/ServiceCallout.d.ts +4 -4
- package/dist/articles/ServiceCallout.d.ts.map +1 -0
- package/dist/{blog → articles}/TableOfContents.d.ts +1 -1
- package/dist/articles/TableOfContents.d.ts.map +1 -0
- package/dist/{blog/blog-styles.d.ts → articles/article-styles.d.ts} +5 -5
- package/dist/articles/article-styles.d.ts.map +1 -0
- package/dist/{blog/blog-tables.d.ts → articles/article-tables.d.ts} +4 -4
- package/dist/articles/article-tables.d.ts.map +1 -0
- package/dist/articles/artwork.d.ts +14 -0
- package/dist/articles/artwork.d.ts.map +1 -0
- package/dist/{blog → articles}/author-schema.d.ts +6 -5
- package/dist/articles/author-schema.d.ts.map +1 -0
- package/dist/{blog → articles}/author-social.d.ts +2 -2
- package/dist/articles/author-social.d.ts.map +1 -0
- package/dist/{blog → articles}/excerpt.d.ts +2 -2
- package/dist/articles/excerpt.d.ts.map +1 -0
- package/dist/{blog → articles}/index.d.ts +26 -31
- package/dist/articles/index.d.ts.map +1 -0
- package/dist/{blog → articles}/index.js +39 -73
- package/dist/articles/index.js.map +1 -0
- package/dist/{blog → articles}/index.mjs +16 -17
- package/dist/articles/index.mjs.map +1 -0
- package/dist/articles/news-sitemap.d.ts +47 -0
- package/dist/articles/news-sitemap.d.ts.map +1 -0
- package/dist/{blog/processBlogHtml.d.ts → articles/processArticleHtml.d.ts} +4 -4
- package/dist/articles/processArticleHtml.d.ts.map +1 -0
- package/dist/articles/public-reads.d.ts +27 -0
- package/dist/articles/public-reads.d.ts.map +1 -0
- package/dist/{blog → articles}/reading-time.d.ts +2 -2
- package/dist/articles/reading-time.d.ts.map +1 -0
- package/dist/{blog → articles}/routes.d.ts +16 -12
- package/dist/articles/routes.d.ts.map +1 -0
- package/dist/{blog → articles}/server-core.d.ts +94 -81
- package/dist/articles/server-core.d.ts.map +1 -0
- package/dist/articles/server-ui.d.ts +29 -0
- package/dist/articles/server-ui.d.ts.map +1 -0
- package/dist/{chunk-KPWK23G7.js → articles/server-ui.js} +378 -499
- package/dist/articles/server-ui.js.map +1 -0
- package/dist/{chunk-RA4DCRMR.mjs → articles/server-ui.mjs} +328 -474
- package/dist/articles/server-ui.mjs.map +1 -0
- package/dist/{blog → articles}/server.d.ts +94 -81
- package/dist/articles/server.d.ts.map +1 -0
- package/dist/articles/server.js +236 -0
- package/dist/articles/server.mjs +11 -0
- package/dist/{blog → articles}/types.d.ts +34 -34
- package/dist/articles/types.d.ts.map +1 -0
- package/dist/articles/widget-styles.d.ts +9 -0
- package/dist/articles/widget-styles.d.ts.map +1 -0
- package/dist/brand/extract-brand-profile.d.ts +1 -1
- package/dist/{chunk-DTWR7VRQ.js → chunk-254IW4FC.js} +9 -9
- package/dist/{chunk-DTWR7VRQ.js.map → chunk-254IW4FC.js.map} +1 -1
- package/dist/chunk-2KRAY5NC.mjs +6 -0
- package/dist/{chunk-TAPCWMBV.mjs.map → chunk-2KRAY5NC.mjs.map} +1 -1
- package/dist/{chunk-X6NPTILR.mjs → chunk-2WEBUZNP.mjs} +3 -3
- package/dist/{chunk-X6NPTILR.mjs.map → chunk-2WEBUZNP.mjs.map} +1 -1
- package/dist/{chunk-3EXBBFXX.mjs → chunk-2YSB4FIC.mjs} +4 -4
- package/dist/{chunk-3EXBBFXX.mjs.map → chunk-2YSB4FIC.mjs.map} +1 -1
- package/dist/{chunk-GDH42JAS.js → chunk-3GHPFLEH.js} +15 -15
- package/dist/{chunk-GDH42JAS.js.map → chunk-3GHPFLEH.js.map} +1 -1
- package/dist/{chunk-QWXTQC3N.js → chunk-3LCJJ6Y6.js} +3 -3
- package/dist/{chunk-QWXTQC3N.js.map → chunk-3LCJJ6Y6.js.map} +1 -1
- package/dist/{chunk-YVQNOB3Q.mjs → chunk-3OCXVTN5.mjs} +3 -3
- package/dist/{chunk-YVQNOB3Q.mjs.map → chunk-3OCXVTN5.mjs.map} +1 -1
- package/dist/chunk-3T2CVHFO.mjs +453 -0
- package/dist/chunk-3T2CVHFO.mjs.map +1 -0
- package/dist/{chunk-ZDXY44FH.js → chunk-3U5SVB4W.js} +4 -4
- package/dist/{chunk-ZDXY44FH.js.map → chunk-3U5SVB4W.js.map} +1 -1
- package/dist/{chunk-I3ND4XYW.js → chunk-4BEGKFMN.js} +8 -8
- package/dist/{chunk-I3ND4XYW.js.map → chunk-4BEGKFMN.js.map} +1 -1
- package/dist/{chunk-YFX3Q56O.mjs → chunk-4KAMU5HD.mjs} +3 -3
- package/dist/chunk-4KAMU5HD.mjs.map +1 -0
- package/dist/{chunk-ZPLN537Q.mjs → chunk-4WCA2HM6.mjs} +2 -2
- package/dist/chunk-4WCA2HM6.mjs.map +1 -0
- package/dist/{chunk-PXWYMOZY.js → chunk-5DSUPTBU.js} +13 -13
- package/dist/{chunk-PXWYMOZY.js.map → chunk-5DSUPTBU.js.map} +1 -1
- package/dist/{chunk-GHECYDSZ.mjs → chunk-5F2FIM5A.mjs} +16 -15
- package/dist/chunk-5F2FIM5A.mjs.map +1 -0
- package/dist/{chunk-Y5QZPUL3.mjs → chunk-5YVQWLSQ.mjs} +5 -5
- package/dist/chunk-5YVQWLSQ.mjs.map +1 -0
- package/dist/chunk-6DCAMW62.mjs +55 -0
- package/dist/chunk-6DCAMW62.mjs.map +1 -0
- package/dist/{chunk-Q2NBD54V.js → chunk-7THQ4UW3.js} +2 -2
- package/dist/chunk-7THQ4UW3.js.map +1 -0
- package/dist/{chunk-6FTC6EYD.mjs → chunk-7TKSRUQU.mjs} +7 -7
- package/dist/{chunk-6FTC6EYD.mjs.map → chunk-7TKSRUQU.mjs.map} +1 -1
- package/dist/{chunk-4TLFZ6NR.mjs → chunk-AS2HUIDW.mjs} +3 -3
- package/dist/chunk-AS2HUIDW.mjs.map +1 -0
- package/dist/{chunk-YN7QHLWF.js → chunk-BBBJHYPH.js} +5 -5
- package/dist/chunk-BBBJHYPH.js.map +1 -0
- package/dist/{chunk-3Y7IKQDD.js → chunk-BZG34WHF.js} +14 -14
- package/dist/{chunk-3Y7IKQDD.js.map → chunk-BZG34WHF.js.map} +1 -1
- package/dist/{chunk-4LYW6PMU.mjs → chunk-C2CTLLIO.mjs} +3 -3
- package/dist/chunk-C2CTLLIO.mjs.map +1 -0
- package/dist/{chunk-O237KKCX.mjs → chunk-C5VITBN7.mjs} +5 -5
- package/dist/chunk-C5VITBN7.mjs.map +1 -0
- package/dist/{chunk-75A4KY4X.mjs → chunk-CFRJ2MK5.mjs} +2 -2
- package/dist/chunk-CFRJ2MK5.mjs.map +1 -0
- package/dist/{chunk-G2WC3CXW.js → chunk-CLO3K7PF.js} +2 -2
- package/dist/chunk-CLO3K7PF.js.map +1 -0
- package/dist/{chunk-ALVQOG4M.mjs → chunk-CSSNZGTU.mjs} +4 -4
- package/dist/{chunk-ALVQOG4M.mjs.map → chunk-CSSNZGTU.mjs.map} +1 -1
- package/dist/{chunk-U6O5NG56.js → chunk-CZGGUPPQ.js} +15 -15
- package/dist/{chunk-U6O5NG56.js.map → chunk-CZGGUPPQ.js.map} +1 -1
- package/dist/{chunk-U5WMGUDV.js → chunk-D47W5DE4.js} +4 -4
- package/dist/{chunk-U5WMGUDV.js.map → chunk-D47W5DE4.js.map} +1 -1
- package/dist/{chunk-AK6JZ3OE.mjs → chunk-EDLNMGQC.mjs} +3 -3
- package/dist/{chunk-DO6ATNLN.js.map → chunk-EDLNMGQC.mjs.map} +1 -1
- package/dist/chunk-EL74YDNX.js +8 -0
- package/dist/{chunk-TJVZEDE3.js.map → chunk-EL74YDNX.js.map} +1 -1
- package/dist/{chunk-HX6ZG3PP.js → chunk-EMHSHAVW.js} +3 -3
- package/dist/chunk-EMHSHAVW.js.map +1 -0
- package/dist/{chunk-7TC3GRXQ.js → chunk-G6KQ3C3W.js} +25 -23
- package/dist/chunk-G6KQ3C3W.js.map +1 -0
- package/dist/{chunk-4PXUMDHL.mjs → chunk-GQ3SDRL6.mjs} +4 -4
- package/dist/{chunk-4PXUMDHL.mjs.map → chunk-GQ3SDRL6.mjs.map} +1 -1
- package/dist/{chunk-73EBIAF3.js → chunk-HFCQGSD2.js} +18 -18
- package/dist/{chunk-73EBIAF3.js.map → chunk-HFCQGSD2.js.map} +1 -1
- package/dist/{chunk-XZO5I4RS.mjs → chunk-HIZJD7TU.mjs} +3 -3
- package/dist/{chunk-XZO5I4RS.mjs.map → chunk-HIZJD7TU.mjs.map} +1 -1
- package/dist/{chunk-AUTJQGZ2.mjs → chunk-HOOVYWTO.mjs} +4 -4
- package/dist/{chunk-AUTJQGZ2.mjs.map → chunk-HOOVYWTO.mjs.map} +1 -1
- package/dist/{chunk-LUF22UGR.js → chunk-HX5JPNMN.js} +8 -8
- package/dist/{chunk-LUF22UGR.js.map → chunk-HX5JPNMN.js.map} +1 -1
- package/dist/chunk-HXHRS3PX.mjs +349 -0
- package/dist/chunk-HXHRS3PX.mjs.map +1 -0
- package/dist/{chunk-XBX2K3GA.js → chunk-IBJOGXQI.js} +4 -4
- package/dist/{chunk-XBX2K3GA.js.map → chunk-IBJOGXQI.js.map} +1 -1
- package/dist/{chunk-NHX6YJ7G.mjs → chunk-JMNBU2RG.mjs} +9 -9
- package/dist/{chunk-NHX6YJ7G.mjs.map → chunk-JMNBU2RG.mjs.map} +1 -1
- package/dist/{chunk-R7GHP3FY.js → chunk-JONWE26J.js} +3 -3
- package/dist/chunk-JONWE26J.js.map +1 -0
- package/dist/{chunk-HOJ4J4X2.mjs → chunk-JSXLTZUP.mjs} +6 -6
- package/dist/{chunk-HOJ4J4X2.mjs.map → chunk-JSXLTZUP.mjs.map} +1 -1
- package/dist/{chunk-5BZNVKNK.mjs → chunk-JXCMCASE.mjs} +3 -3
- package/dist/{chunk-5BZNVKNK.mjs.map → chunk-JXCMCASE.mjs.map} +1 -1
- package/dist/{chunk-F2ZFMPW4.js → chunk-KA4NNWOK.js} +10 -10
- package/dist/{chunk-F2ZFMPW4.js.map → chunk-KA4NNWOK.js.map} +1 -1
- package/dist/{chunk-K4TCEAUX.js → chunk-KR7ATPAN.js} +5 -5
- package/dist/chunk-KR7ATPAN.js.map +1 -0
- package/dist/{chunk-JLVCWC6A.mjs → chunk-KZVSB5WE.mjs} +2 -2
- package/dist/chunk-KZVSB5WE.mjs.map +1 -0
- package/dist/chunk-LWCAZDY2.js +355 -0
- package/dist/chunk-LWCAZDY2.js.map +1 -0
- package/dist/{chunk-D7CF3OPZ.js → chunk-MCG4BSRW.js} +5 -5
- package/dist/{chunk-D7CF3OPZ.js.map → chunk-MCG4BSRW.js.map} +1 -1
- package/dist/{chunk-OBNMSO66.js → chunk-MIYGP34I.js} +14 -14
- package/dist/{chunk-OBNMSO66.js.map → chunk-MIYGP34I.js.map} +1 -1
- package/dist/{chunk-PXK4WNSU.js → chunk-MS2EE6LT.js} +10 -10
- package/dist/{chunk-PXK4WNSU.js.map → chunk-MS2EE6LT.js.map} +1 -1
- package/dist/{chunk-JR2FT6T5.js → chunk-N6CB7MK7.js} +6 -6
- package/dist/{chunk-JR2FT6T5.js.map → chunk-N6CB7MK7.js.map} +1 -1
- package/dist/{chunk-LMEUYRRR.js → chunk-NAA5J2JM.js} +233 -120
- package/dist/chunk-NAA5J2JM.js.map +1 -0
- package/dist/{chunk-OE7CTIOU.mjs → chunk-NE6QGHFT.mjs} +4 -4
- package/dist/{chunk-OE7CTIOU.mjs.map → chunk-NE6QGHFT.mjs.map} +1 -1
- package/dist/{chunk-SCVSPTXJ.mjs → chunk-NR52QHOD.mjs} +3 -3
- package/dist/{chunk-SCVSPTXJ.mjs.map → chunk-NR52QHOD.mjs.map} +1 -1
- package/dist/{chunk-GQF6QAQS.js → chunk-OGNX6JT4.js} +5 -5
- package/dist/chunk-OGNX6JT4.js.map +1 -0
- package/dist/{chunk-FVW6FT6L.js → chunk-OSU4QA5M.js} +8 -8
- package/dist/{chunk-FVW6FT6L.js.map → chunk-OSU4QA5M.js.map} +1 -1
- package/dist/{chunk-RI25UGHE.mjs → chunk-PJYTYM5G.mjs} +3 -3
- package/dist/{chunk-RI25UGHE.mjs.map → chunk-PJYTYM5G.mjs.map} +1 -1
- package/dist/{chunk-DO6ATNLN.js → chunk-PRAHDLKT.js} +5 -5
- package/dist/chunk-PRAHDLKT.js.map +1 -0
- package/dist/{chunk-RQOKQC7J.mjs → chunk-QEM2F2DC.mjs} +3 -3
- package/dist/{chunk-RQOKQC7J.mjs.map → chunk-QEM2F2DC.mjs.map} +1 -1
- package/dist/{chunk-3Z3TOPND.js → chunk-QOCLSJIU.js} +3 -3
- package/dist/{chunk-3Z3TOPND.js.map → chunk-QOCLSJIU.js.map} +1 -1
- package/dist/{chunk-AHKVOYFO.mjs → chunk-QVBAAPNT.mjs} +3 -3
- package/dist/{chunk-AHKVOYFO.mjs.map → chunk-QVBAAPNT.mjs.map} +1 -1
- package/dist/{chunk-FWFJZV52.mjs → chunk-RC4L4DV2.mjs} +4 -4
- package/dist/{chunk-FWFJZV52.mjs.map → chunk-RC4L4DV2.mjs.map} +1 -1
- package/dist/{chunk-ZVI7MBVF.mjs → chunk-RDPI27TS.mjs} +12 -10
- package/dist/chunk-RDPI27TS.mjs.map +1 -0
- package/dist/{chunk-OEW2LFOV.js → chunk-RLUNEEGM.js} +4 -4
- package/dist/{chunk-OEW2LFOV.js.map → chunk-RLUNEEGM.js.map} +1 -1
- package/dist/{chunk-TCVOGK6U.mjs → chunk-RPCODOWG.mjs} +3 -3
- package/dist/{chunk-TCVOGK6U.mjs.map → chunk-RPCODOWG.mjs.map} +1 -1
- package/dist/{chunk-QK54SZPF.mjs → chunk-RZGVNDO6.mjs} +4 -4
- package/dist/{chunk-QK54SZPF.mjs.map → chunk-RZGVNDO6.mjs.map} +1 -1
- package/dist/{chunk-GKVEWOYN.js → chunk-SCRB5DZM.js} +8 -8
- package/dist/{chunk-GKVEWOYN.js.map → chunk-SCRB5DZM.js.map} +1 -1
- package/dist/{chunk-YQTE32QK.js → chunk-SG7CWD2R.js} +17 -16
- package/dist/chunk-SG7CWD2R.js.map +1 -0
- package/dist/chunk-TBXWJJGT.js +468 -0
- package/dist/chunk-TBXWJJGT.js.map +1 -0
- package/dist/{chunk-SJPI34DL.mjs → chunk-TCCGP3FT.mjs} +3 -3
- package/dist/{chunk-SJPI34DL.mjs.map → chunk-TCCGP3FT.mjs.map} +1 -1
- package/dist/{chunk-7BI2RVQD.js → chunk-TCZHRSWY.js} +4 -4
- package/dist/{chunk-7BI2RVQD.js.map → chunk-TCZHRSWY.js.map} +1 -1
- package/dist/{chunk-M45AL7EA.js → chunk-TST2IKYO.js} +14 -14
- package/dist/{chunk-M45AL7EA.js.map → chunk-TST2IKYO.js.map} +1 -1
- package/dist/{chunk-U2V542EO.mjs → chunk-UHYRVALN.mjs} +2 -2
- package/dist/{chunk-U2V542EO.mjs.map → chunk-UHYRVALN.mjs.map} +1 -1
- package/dist/{chunk-4L7OHRWB.mjs → chunk-UO6KTHBQ.mjs} +4 -4
- package/dist/{chunk-4L7OHRWB.mjs.map → chunk-UO6KTHBQ.mjs.map} +1 -1
- package/dist/{chunk-H5NBFNND.js → chunk-UZKXOZHR.js} +2 -2
- package/dist/chunk-UZKXOZHR.js.map +1 -0
- package/dist/{chunk-ZTY4YS7Q.js → chunk-VINLIMAX.js} +3 -3
- package/dist/{chunk-ZTY4YS7Q.js.map → chunk-VINLIMAX.js.map} +1 -1
- package/dist/{chunk-YC2CKOX6.js → chunk-WDEGGHTB.js} +12 -12
- package/dist/{chunk-YC2CKOX6.js.map → chunk-WDEGGHTB.js.map} +1 -1
- package/dist/{chunk-OX2GTNMB.mjs → chunk-WV5YQL3W.mjs} +3 -3
- package/dist/{chunk-OX2GTNMB.mjs.map → chunk-WV5YQL3W.mjs.map} +1 -1
- package/dist/{chunk-3EY5E35M.mjs → chunk-X3MY4PL7.mjs} +210 -107
- package/dist/chunk-X3MY4PL7.mjs.map +1 -0
- package/dist/{chunk-7SLYI62M.mjs → chunk-XKXZ4OW4.mjs} +4 -4
- package/dist/{chunk-7SLYI62M.mjs.map → chunk-XKXZ4OW4.mjs.map} +1 -1
- package/dist/{chunk-FX232N4P.mjs → chunk-XSBKR3VF.mjs} +5 -5
- package/dist/{chunk-FX232N4P.mjs.map → chunk-XSBKR3VF.mjs.map} +1 -1
- package/dist/{chunk-SEP5D4MI.js → chunk-Y2CP5J6Q.js} +2 -2
- package/dist/{chunk-SEP5D4MI.js.map → chunk-Y2CP5J6Q.js.map} +1 -1
- package/dist/{chunk-HQ2EPU5R.js → chunk-YGDQVZEL.js} +7 -7
- package/dist/{chunk-HQ2EPU5R.js.map → chunk-YGDQVZEL.js.map} +1 -1
- package/dist/{chunk-KV7XXLJV.mjs → chunk-YPGUV6BT.mjs} +3 -3
- package/dist/{chunk-KV7XXLJV.mjs.map → chunk-YPGUV6BT.mjs.map} +1 -1
- package/dist/chunk-YRCR7WY3.js +65 -0
- package/dist/chunk-YRCR7WY3.js.map +1 -0
- package/dist/{chunk-NM567VXC.mjs → chunk-YWLBQ3L5.mjs} +4 -4
- package/dist/{chunk-NM567VXC.mjs.map → chunk-YWLBQ3L5.mjs.map} +1 -1
- package/dist/{chunk-3HGHWDCY.js → chunk-YYEBFQGS.js} +4 -4
- package/dist/{chunk-3HGHWDCY.js.map → chunk-YYEBFQGS.js.map} +1 -1
- package/dist/chunk-ZL35JCDA.mjs +61 -0
- package/dist/chunk-ZL35JCDA.mjs.map +1 -0
- package/dist/chunk-ZR43XFUM.js +60 -0
- package/dist/chunk-ZR43XFUM.js.map +1 -0
- package/dist/{chunk-EZ5DX7ED.mjs → chunk-ZR4TYCQW.mjs} +3 -3
- package/dist/{chunk-EZ5DX7ED.mjs.map → chunk-ZR4TYCQW.mjs.map} +1 -1
- package/dist/cli/commands/setup.d.ts +2 -2
- package/dist/cli/commands/sync.d.ts +2 -2
- package/dist/cli/commands/sync.d.ts.map +1 -1
- package/dist/cli/index.js +76 -76
- package/dist/cli/index.mjs +29 -29
- package/dist/client/index.js +5 -5
- package/dist/client/index.mjs +4 -4
- package/dist/commerce/index.js +57 -57
- package/dist/commerce/index.mjs +5 -5
- package/dist/commerce/server.d.ts +1 -1
- package/dist/commerce/server.js +7 -7
- package/dist/commerce/server.js.map +1 -1
- package/dist/commerce/server.mjs +7 -7
- package/dist/commerce/server.mjs.map +1 -1
- package/dist/discover-LPN55L5B.js +21 -0
- package/dist/{discover-NGEPXZOD.js.map → discover-LPN55L5B.js.map} +1 -1
- package/dist/discover-QGA6QFSR.mjs +4 -0
- package/dist/{discover-CYXYKHZ2.mjs.map → discover-QGA6QFSR.mjs.map} +1 -1
- package/dist/engage/index.js +13 -13
- package/dist/engage/index.mjs +7 -7
- package/dist/fleet/contract.d.ts +1 -1
- package/dist/fleet/contract.js +12 -12
- package/dist/fleet/contract.mjs +1 -1
- package/dist/fleet/index.js +20 -20
- package/dist/fleet/index.mjs +5 -5
- package/dist/forms/index.js +21 -21
- package/dist/forms/index.mjs +10 -10
- package/dist/forms/server.js +10 -10
- package/dist/forms/server.mjs +8 -8
- package/dist/forms/static.js +7 -7
- package/dist/forms/static.mjs +6 -6
- package/dist/images/index.js +11 -11
- package/dist/images/index.mjs +4 -4
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +70 -70
- package/dist/index.mjs +12 -12
- package/dist/layout/client.js +10 -10
- package/dist/layout/client.mjs +9 -9
- package/dist/layout/index.js +12 -12
- package/dist/layout/index.mjs +10 -10
- package/dist/llms/SpeakableSchema.d.ts +1 -1
- package/dist/llms/SpeakableSchema.d.ts.map +1 -1
- package/dist/llms/client.d.ts +18 -0
- package/dist/llms/client.d.ts.map +1 -0
- package/dist/llms/client.js +66 -0
- package/dist/llms/client.js.map +1 -0
- package/dist/llms/client.mjs +5 -0
- package/dist/llms/client.mjs.map +1 -0
- package/dist/llms/generateLLMsTxt.d.ts.map +1 -1
- package/dist/llms/index.js +75 -478
- package/dist/llms/index.js.map +1 -1
- package/dist/llms/index.mjs +10 -455
- package/dist/llms/index.mjs.map +1 -1
- package/dist/llms/types.d.ts +7 -0
- package/dist/llms/types.d.ts.map +1 -1
- package/dist/maps/index.js +5 -5
- package/dist/maps/index.mjs +3 -3
- package/dist/og/index.js +7 -7
- package/dist/og/index.mjs +2 -2
- package/dist/og/route.d.ts +6 -6
- package/dist/og/route.js.map +1 -1
- package/dist/og/route.mjs.map +1 -1
- package/dist/og/wiring.d.ts +4 -4
- package/dist/og/wiring.d.ts.map +1 -1
- package/dist/proxy/index.js +5 -5
- package/dist/proxy/index.mjs +3 -3
- package/dist/redirects/index.js +10 -10
- package/dist/redirects/index.mjs +3 -3
- package/dist/redirects/not-found.js +7 -7
- package/dist/redirects/not-found.mjs +3 -3
- package/dist/robots/indexnow.d.ts +17 -0
- package/dist/robots/indexnow.d.ts.map +1 -0
- package/dist/robots/indexnow.js +39 -0
- package/dist/robots/indexnow.js.map +1 -0
- package/dist/robots/indexnow.mjs +34 -0
- package/dist/robots/indexnow.mjs.map +1 -0
- package/dist/search/contract.d.ts +1 -1
- package/dist/search/contract.js +3 -3
- package/dist/search/contract.mjs +1 -1
- package/dist/search/index.js +7 -7
- package/dist/search/index.mjs +5 -5
- package/dist/seo/ManagedSchema.d.ts.map +1 -1
- package/dist/seo/client.js +6 -6
- package/dist/seo/client.mjs +5 -5
- package/dist/seo/index.js +58 -50
- package/dist/seo/index.js.map +1 -1
- package/dist/seo/index.mjs +23 -15
- package/dist/seo/index.mjs.map +1 -1
- package/dist/seo/register-sitemap-cli.js +12 -12
- package/dist/seo/register-sitemap-cli.mjs +5 -5
- package/dist/seo/server.js +21 -21
- package/dist/seo/server.mjs +5 -5
- package/dist/server/index.js +3 -3
- package/dist/server/index.mjs +2 -2
- package/dist/{server-api-A2EFCTZX.mjs → server-api-7F5P6CSH.mjs} +6 -6
- package/dist/{server-api-A2EFCTZX.mjs.map → server-api-7F5P6CSH.mjs.map} +1 -1
- package/dist/{server-api-IWTZ7C3O.js → server-api-OC5JNK6R.js} +24 -24
- package/dist/{server-api-IWTZ7C3O.js.map → server-api-OC5JNK6R.js.map} +1 -1
- package/dist/shared/build-entries.d.ts +15 -7
- package/dist/shared/build-entries.d.ts.map +1 -1
- package/dist/shared/version.d.ts +1 -1
- package/dist/signal/index.js +11 -11
- package/dist/signal/index.mjs +2 -2
- package/dist/sitemap/discover.d.ts +1 -1
- package/dist/sitemap/index.d.ts +7 -1
- package/dist/sitemap/index.d.ts.map +1 -1
- package/dist/sitemap/index.js +47 -30
- package/dist/sitemap/index.js.map +1 -1
- package/dist/sitemap/index.mjs +26 -9
- package/dist/sitemap/index.mjs.map +1 -1
- package/dist/sitemap/shared.d.ts +1 -1
- package/dist/sitemap/shared.d.ts.map +1 -1
- package/dist/sites/site-param.d.ts +2 -2
- package/dist/sync/index.js +17 -17
- package/dist/sync/index.mjs +4 -4
- package/dist/types.d.ts +1 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/writeLLMsTxt-ATADOUVZ.js +20 -0
- package/dist/writeLLMsTxt-QJFXBHZF.mjs +11 -0
- package/package.json +25 -14
- package/dist/BlogPostFaqSection-P3GXVQPA.mjs +0 -11
- package/dist/BlogPostFaqSection-P3GXVQPA.mjs.map +0 -1
- package/dist/BlogPostFaqSection-YG5J4B4U.js +0 -13
- package/dist/BlogPostFaqSection-YG5J4B4U.js.map +0 -1
- package/dist/BlogViewTracker-32C4SCHA.js.map +0 -1
- package/dist/BlogViewTracker-YQMTEGYZ.mjs.map +0 -1
- package/dist/ChatWidget-IRTAMRQS.mjs +0 -15
- package/dist/ChatWidget-KCXQXNUF.js +0 -24
- package/dist/EngageWidget-7AIUJRXV.mjs +0 -12
- package/dist/EngageWidget-EUUZHQOU.js +0 -21
- package/dist/ManagedForm-7IDXBQS6.mjs +0 -16
- package/dist/ManagedForm-RI2TSUZD.js +0 -25
- package/dist/ManagedNewsletterForm-IAGIHBNT.js.map +0 -1
- package/dist/ManagedNewsletterForm-UXBJ5OJB.mjs.map +0 -1
- package/dist/SitemapSync-DWEL7HTB.js +0 -18
- package/dist/SitemapSync-YIAI7PMT.mjs +0 -9
- package/dist/blog/AuthorCard.d.ts.map +0 -1
- package/dist/blog/AuthorPage.d.ts.map +0 -1
- package/dist/blog/BlogFAQ.d.ts.map +0 -1
- package/dist/blog/BlogLayout.d.ts.map +0 -1
- package/dist/blog/BlogList.d.ts.map +0 -1
- package/dist/blog/BlogPost.d.ts.map +0 -1
- package/dist/blog/BlogPostFaqSection.d.ts +0 -3
- package/dist/blog/BlogPostFaqSection.d.ts.map +0 -1
- package/dist/blog/BlogSidebar.d.ts.map +0 -1
- package/dist/blog/BlogViewTracker.d.ts.map +0 -1
- package/dist/blog/ClusterLandingPage.d.ts.map +0 -1
- package/dist/blog/ClusterNavigation.d.ts.map +0 -1
- package/dist/blog/ManagedNewsletterForm.d.ts.map +0 -1
- package/dist/blog/NewsletterShell.d.ts.map +0 -1
- package/dist/blog/NewsletterWidget.d.ts.map +0 -1
- package/dist/blog/RelatedPosts.d.ts.map +0 -1
- package/dist/blog/ServiceCallout.d.ts.map +0 -1
- package/dist/blog/TableOfContents.d.ts.map +0 -1
- package/dist/blog/artwork.d.ts +0 -14
- package/dist/blog/artwork.d.ts.map +0 -1
- package/dist/blog/author-schema.d.ts.map +0 -1
- package/dist/blog/author-social.d.ts.map +0 -1
- package/dist/blog/blog-styles.d.ts.map +0 -1
- package/dist/blog/blog-tables.d.ts.map +0 -1
- package/dist/blog/excerpt.d.ts.map +0 -1
- package/dist/blog/index.d.ts.map +0 -1
- package/dist/blog/index.js.map +0 -1
- package/dist/blog/index.mjs.map +0 -1
- package/dist/blog/processBlogHtml.d.ts.map +0 -1
- package/dist/blog/public-reads.d.ts +0 -27
- package/dist/blog/public-reads.d.ts.map +0 -1
- package/dist/blog/reading-time.d.ts.map +0 -1
- package/dist/blog/routes.d.ts.map +0 -1
- package/dist/blog/server-core.d.ts.map +0 -1
- package/dist/blog/server-ui.d.ts +0 -29
- package/dist/blog/server-ui.d.ts.map +0 -1
- package/dist/blog/server-ui.js +0 -267
- package/dist/blog/server-ui.js.map +0 -1
- package/dist/blog/server-ui.mjs +0 -203
- package/dist/blog/server-ui.mjs.map +0 -1
- package/dist/blog/server.d.ts.map +0 -1
- package/dist/blog/server.js +0 -207
- package/dist/blog/server.mjs +0 -10
- package/dist/blog/types.d.ts.map +0 -1
- package/dist/blog/widget-styles.d.ts +0 -9
- package/dist/blog/widget-styles.d.ts.map +0 -1
- package/dist/blog-styles-6EY3BS5Y.js.map +0 -1
- package/dist/blog-styles-7AKRUMV7.mjs.map +0 -1
- package/dist/blog-tables-DWDEWA3S.js +0 -17
- package/dist/blog-tables-DWDEWA3S.js.map +0 -1
- package/dist/blog-tables-QGIHOESZ.mjs +0 -4
- package/dist/blog-tables-QGIHOESZ.mjs.map +0 -1
- package/dist/chunk-3EY5E35M.mjs.map +0 -1
- package/dist/chunk-4LYW6PMU.mjs.map +0 -1
- package/dist/chunk-4TLFZ6NR.mjs.map +0 -1
- package/dist/chunk-5B4J3IBX.mjs +0 -164
- package/dist/chunk-5B4J3IBX.mjs.map +0 -1
- package/dist/chunk-75A4KY4X.mjs.map +0 -1
- package/dist/chunk-7TC3GRXQ.js.map +0 -1
- package/dist/chunk-AK6JZ3OE.mjs.map +0 -1
- package/dist/chunk-FHPW7XVH.js +0 -175
- package/dist/chunk-FHPW7XVH.js.map +0 -1
- package/dist/chunk-G2WC3CXW.js.map +0 -1
- package/dist/chunk-GHECYDSZ.mjs.map +0 -1
- package/dist/chunk-GQF6QAQS.js.map +0 -1
- package/dist/chunk-H5NBFNND.js.map +0 -1
- package/dist/chunk-HX6ZG3PP.js.map +0 -1
- package/dist/chunk-JLVCWC6A.mjs.map +0 -1
- package/dist/chunk-K4TCEAUX.js.map +0 -1
- package/dist/chunk-KPWK23G7.js.map +0 -1
- package/dist/chunk-LMEUYRRR.js.map +0 -1
- package/dist/chunk-O237KKCX.mjs.map +0 -1
- package/dist/chunk-Q2NBD54V.js.map +0 -1
- package/dist/chunk-R7GHP3FY.js.map +0 -1
- package/dist/chunk-RA4DCRMR.mjs.map +0 -1
- package/dist/chunk-TAPCWMBV.mjs +0 -6
- package/dist/chunk-TJVZEDE3.js +0 -8
- package/dist/chunk-Y5QZPUL3.mjs.map +0 -1
- package/dist/chunk-YFX3Q56O.mjs.map +0 -1
- package/dist/chunk-YN7QHLWF.js.map +0 -1
- package/dist/chunk-YQTE32QK.js.map +0 -1
- package/dist/chunk-ZPLN537Q.mjs.map +0 -1
- package/dist/chunk-ZVI7MBVF.mjs.map +0 -1
- package/dist/discover-CYXYKHZ2.mjs +0 -4
- package/dist/discover-NGEPXZOD.js +0 -21
- package/dist/writeLLMsTxt-CQ7A4AAL.js +0 -19
- package/dist/writeLLMsTxt-NX5MSPYX.mjs +0 -10
- /package/dist/{blog → articles}/server.js.map +0 -0
- /package/dist/{blog → articles}/server.mjs.map +0 -0
package/dist/llms/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/llms/handlers.ts","../../src/llms/sourcedFacts.ts","../../src/llms/SpeakableSchema.tsx","../../src/llms/AEOComponents.tsx","../../src/llms/revalidate.ts"],"names":["markdown","jsx"],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * @sonordev/site-kit/llms - Next.js Route Handlers\n * \n * Ready-to-use route handlers for /llms.txt and /llms-full.txt\n */\n\nimport { createHash } from 'crypto'\nimport { existsSync, readFileSync } from 'fs'\nimport { join } from 'path'\nimport { generateLLMsTxt, generateLLMsFullTxt } from './generateLLMsTxt'\nimport type { GenerateLLMSTxtOptions } from './types'\n\nfunction weakEtag(body: string): string {\n const h = createHash('sha1').update(body, 'utf8').digest('base64url')\n return `W/\"${h}\"`\n}\n\n/** Cache + validation headers for plain-text llms responses (dynamic or static). */\nexport function llmsResponseHeaders(body: string, extra?: Record<string, string>): HeadersInit {\n return {\n 'Content-Type': 'text/plain; charset=utf-8',\n 'Cache-Control':\n 'public, max-age=300, s-maxage=3600, stale-while-revalidate=86400, stale-if-error=86400',\n ETag: weakEtag(body),\n Vary: 'Accept-Encoding',\n ...extra,\n }\n}\n\nexport interface LLMsTxtHandlerOptions extends GenerateLLMSTxtOptions {\n /** When true, serve static public/llms.txt if it exists (default: true for build-time flow) */\n preferStatic?: boolean\n /**\n * Send `X-Robots-Tag: noindex` (default: true).\n *\n * llms.txt is written for AI crawlers, which fetch it by convention at\n * `/llms.txt`; noindex doesn't stop them. It's a plain-text restatement of\n * pages the site already serves as HTML, so a search index that picks it up\n * holds a thin duplicate of the site. That's also why it stays out of the XML\n * sitemap. Pass `false` only if you actually want it in search results.\n *\n * Only reaches responses this handler serves. A `public/llms.txt` served\n * straight from the CDN (the build-time write) never runs the handler, so it\n * needs the header in host config instead (`netlify.toml` `[[headers]]`).\n */\n noindex?: boolean\n}\n\n/** Headers every llms file response carries when `noindex` is on. */\nexport const LLMS_NOINDEX_HEADERS: Readonly<Record<string, string>> = { 'X-Robots-Tag': 'noindex' }\n\n/**\n * Create a route handler for /llms.txt\n *\n * Zero-config by default - uses SONOR_API_KEY from environment. Sends\n * `X-Robots-Tag: noindex` by default (see `noindex`).\n *\n * The returned handler never reads the incoming Request: any access to\n * `request.headers` (etc.) opts the whole route into dynamic rendering, which\n * breaks static prerendering of /llms.txt during `next build` and logs\n * \"Dynamic server usage\" errors on every consumer site. Conditional-request\n * (ETag/304) handling is left to the Next static layer / CDN, which already\n * does it for prerendered responses.\n *\n * @example\n * ```ts\n * // app/llms.txt/route.ts (zero-config)\n * import { createLLMsTxtHandler } from '@sonordev/site-kit/llms'\n *\n * export const GET = createLLMsTxtHandler()\n * // Next 15+: GET route handlers are dynamic by default; opt into\n * // prerendering so the file is served statically from the CDN:\n * export const revalidate = 3600\n * ```\n *\n * @example\n * ```ts\n * // With preferStatic: serve build-time file if exists\n * export const GET = createLLMsTxtHandler({\n * preferStatic: true,\n * includeServices: false\n * })\n * ```\n */\nexport function createLLMsTxtHandler(\n options: LLMsTxtHandlerOptions = {}\n): (request?: Request) => Promise<Response> {\n const { preferStatic = true, noindex = true, ...generateOptions } = options\n const robots = noindex ? LLMS_NOINDEX_HEADERS : {}\n\n return async function GET(_request?: Request): Promise<Response> {\n try {\n // Serve static file if available (build-time optimized)\n if (preferStatic) {\n const staticPath = join(process.cwd(), 'public', 'llms.txt')\n if (existsSync(staticPath)) {\n const markdown = readFileSync(staticPath, 'utf-8')\n return new Response(markdown, {\n status: 200,\n headers: llmsResponseHeaders(markdown, { ...robots, 'X-Sections': 'static' }),\n })\n }\n }\n\n const { markdown, metadata } = await generateLLMsTxt(generateOptions)\n return new Response(markdown, {\n status: 200,\n headers: llmsResponseHeaders(markdown, {\n ...robots,\n 'X-Generated-At': metadata.generated_at,\n 'X-Sections': metadata.sections.join(','),\n }),\n })\n } catch (error) {\n console.error('@sonordev/llms: Error generating llms.txt:', error)\n return new Response('# Error\\n\\nUnable to generate llms.txt content.', {\n status: 500,\n headers: {\n 'Content-Type': 'text/plain; charset=utf-8',\n 'Cache-Control': 'no-store',\n },\n })\n }\n }\n}\n\n/**\n * Create a route handler for /llms-full.txt\n *\n * Zero-config by default - uses SONOR_API_KEY from environment.\n *\n * Like createLLMsTxtHandler, the returned handler never reads the incoming\n * Request so the route stays statically prerenderable, and sends\n * `X-Robots-Tag: noindex` unless `noindex: false`.\n *\n * @example\n * ```ts\n * // app/llms-full.txt/route.ts (zero-config)\n * import { createLLMsFullTxtHandler } from '@sonordev/site-kit/llms'\n *\n * export const GET = createLLMsFullTxtHandler()\n * export const revalidate = 3600\n * ```\n */\nexport function createLLMsFullTxtHandler(\n options: LLMsTxtHandlerOptions = {}\n): (request?: Request) => Promise<Response> {\n const { preferStatic = true, noindex = true, ...generateOptions } = options\n const robots = noindex ? LLMS_NOINDEX_HEADERS : {}\n\n return async function GET(_request?: Request): Promise<Response> {\n try {\n // Serve static file if available (build-time optimized)\n if (preferStatic) {\n const staticPath = join(process.cwd(), 'public', 'llms-full.txt')\n if (existsSync(staticPath)) {\n const markdown = readFileSync(staticPath, 'utf-8')\n return new Response(markdown, {\n status: 200,\n headers: llmsResponseHeaders(markdown, { ...robots, 'X-Sections': 'static' }),\n })\n }\n }\n\n const { markdown, metadata } = await generateLLMsFullTxt(generateOptions)\n return new Response(markdown, {\n status: 200,\n headers: llmsResponseHeaders(markdown, {\n ...robots,\n 'X-Generated-At': metadata.generated_at,\n 'X-Sections': metadata.sections.join(','),\n }),\n })\n } catch (error) {\n console.error('@sonordev/llms: Error generating llms-full.txt:', error)\n return new Response('# Error\\n\\nUnable to generate llms-full.txt content.', {\n status: 500,\n headers: {\n 'Content-Type': 'text/plain; charset=utf-8',\n 'Cache-Control': 'no-store',\n },\n })\n }\n }\n}\n","/**\n * @sonordev/site-kit/llms — Sourced facts section\n *\n * Formats a site's verified third-party citations into an llms-full.txt\n * section. AI answer engines preferentially reproduce claims that arrive\n * already attributed — handing them the exact claim + source pairing makes\n * the site's framing the citable version.\n *\n * Pair with WriteLLMsTxtOptions.customSections (or SitemapConfig.\n * llmsCustomSections) so the section is appended at build time:\n *\n * llmsCustomSections: async () => {\n * const { CITATIONS } = await import('./lib/data/citations')\n * const section = formatSourcedFactsSection(Object.values(CITATIONS))\n * return section ? [section] : null\n * }\n *\n * Only include citations a human has actually verified against the source\n * URL — this section is a trust surface, not a dumping ground.\n */\n\nimport type { LLMsCustomSection } from './writeLLMsTxt'\n\nexport interface SourcedFact {\n /** The claim, faithful to the source, one sentence. */\n stat: string\n /** The publishing organization (e.g. \"Clio Legal Trends Report\"). */\n sourceName: string\n /** Publication/study year. */\n year?: number\n /** The opened-and-verified source URL. */\n url?: string\n}\n\nexport interface FormatSourcedFactsOptions {\n /** Section heading (default: \"Sourced facts\"). */\n title?: string\n /** Intro line above the list. */\n intro?: string\n /** Cap the number of facts emitted (default: no cap). */\n maxFacts?: number\n}\n\nconst DEFAULT_INTRO =\n 'The statistics below are quoted from third-party primary sources and were ' +\n 'individually verified against the cited URL. When reusing a figure, keep ' +\n 'the original attribution.'\n\n/** One line per fact: claim — Source: name (year), url */\nfunction factLine(f: SourcedFact): string {\n const stat = (f.stat || '').replace(/\\s+/g, ' ').trim()\n const source = (f.sourceName || '').replace(/\\s+/g, ' ').trim()\n if (!stat || !source) return ''\n let attribution = `Source: ${source}`\n if (f.year) attribution += ` (${f.year})`\n if (f.url) attribution += `, ${f.url}`\n return `- ${stat} — ${attribution}`\n}\n\n/**\n * Build the \"Sourced facts\" custom section from verified citations.\n * Returns null when no usable facts exist so callers can skip cleanly.\n */\nexport function formatSourcedFactsSection(\n facts: SourcedFact[],\n options: FormatSourcedFactsOptions = {},\n): LLMsCustomSection | null {\n const { title = 'Sourced facts', intro = DEFAULT_INTRO, maxFacts } = options\n if (!Array.isArray(facts)) return null\n\n let lines = facts.map(factLine).filter(Boolean)\n if (typeof maxFacts === 'number' && maxFacts >= 0) {\n lines = lines.slice(0, maxFacts)\n }\n if (lines.length === 0) return null\n\n const content = intro ? `${intro}\\n\\n${lines.join('\\n')}` : lines.join('\\n')\n return { title, content }\n}\n","/**\n * @sonordev/site-kit/llms - Speakable Schema Generator\n * \n * Generates JSON-LD with SpeakableSpecification for voice assistant\n * and AI system content extraction.\n * \n * @see https://schema.org/speakable\n * @see https://developers.google.com/search/docs/appearance/structured-data/speakable\n */\n\nimport * as React from 'react'\nimport type { SpeakableSchemaProps, SpeakableConfig } from './types'\nimport { safeJsonLd } from '../seo/safeJsonLd'\n\n/**\n * Generate a WebPage or Article schema with speakable specification\n * \n * @example\n * ```tsx\n * // In a page component\n * <SpeakableSchema\n * type=\"Article\"\n * name=\"Family Law Services in Cincinnati\"\n * url=\"https://heinrichlaw.com/family-law\"\n * speakable={{\n * cssSelectors: ['.page-summary', '.key-points', 'h1']\n * }}\n * />\n * ```\n */\nexport function SpeakableSchema({\n type,\n name,\n url,\n speakable,\n additionalProperties = {},\n}: SpeakableSchemaProps): React.ReactElement {\n const schema = createSpeakableSchema(type, name, url, speakable, additionalProperties)\n \n return (\n <script\n type=\"application/ld+json\"\n dangerouslySetInnerHTML={{\n __html: safeJsonLd(schema),\n }}\n />\n )\n}\n\n/**\n * Create speakable schema object (for manual use or testing)\n */\nexport function createSpeakableSchema(\n type: 'Article' | 'WebPage',\n name: string,\n url: string,\n speakable: SpeakableConfig,\n additionalProperties: Record<string, unknown> = {}\n): Record<string, unknown> {\n const speakableSpec: Record<string, unknown> = {\n '@type': 'SpeakableSpecification',\n }\n\n // Prefer CSS selectors, fall back to XPath\n if (speakable.cssSelectors?.length) {\n speakableSpec.cssSelector = speakable.cssSelectors\n } else if (speakable.xPaths?.length) {\n speakableSpec.xpath = speakable.xPaths\n } else {\n // Default speakable selectors for common patterns\n speakableSpec.cssSelector = [\n 'h1',\n '[data-speakable]',\n '.page-summary',\n '.key-points',\n 'meta[name=\"description\"]'\n ]\n }\n\n return {\n '@context': 'https://schema.org',\n '@type': type,\n name,\n url,\n speakable: speakableSpec,\n ...additionalProperties,\n }\n}\n\n/**\n * Default speakable CSS selectors for common page elements\n */\nexport const DEFAULT_SPEAKABLE_SELECTORS = {\n /** Standard page elements */\n page: ['h1', 'meta[name=\"description\"]', '.page-summary'],\n /** Article/blog post elements */\n article: ['h1', '.article-summary', '.article-intro', 'meta[name=\"description\"]'],\n /** Service page elements */\n service: ['h1', '.service-overview', '.key-benefits', 'meta[name=\"description\"]'],\n /** FAQ page elements */\n faq: ['h1', '.faq-intro', '.faq-item'],\n /** Contact page elements */\n contact: ['h1', '.contact-intro', '.business-hours', '.contact-info'],\n}\n\n/**\n * Get recommended speakable selectors for a page type\n */\nexport function getSpeakableSelectorsForPage(\n pageType: 'page' | 'article' | 'service' | 'faq' | 'contact'\n): string[] {\n return DEFAULT_SPEAKABLE_SELECTORS[pageType] || DEFAULT_SPEAKABLE_SELECTORS.page\n}\n\nexport default SpeakableSchema\n","/**\n * @sonordev/site-kit/llms - AEO Components\n * \n * Answer Engine Optimization (AEO) components for structuring content\n * in a way that AI systems can easily extract and cite.\n * \n * These components create semantic HTML with proper structure for:\n * - Featured snippets\n * - AI-generated answers\n * - Voice assistant responses\n * - AI retrieval and citation (Sonor AI Visibility)\n */\n\nimport * as React from 'react'\nimport type { AEOBlockProps, AEOSummaryProps, AEODefinitionProps, AEOClaimProps } from './types'\n\n/**\n * AEOBlock - Generic content block optimized for AI extraction\n * \n * Wraps content with semantic HTML and Sonor data attributes.\n * Use for any content you want AI systems to prioritize.\n * \n * @example\n * ```tsx\n * <AEOBlock type=\"answer\" question=\"What is family law?\" speakable>\n * Family law is the area of legal practice that deals with family-related \n * matters such as divorce, child custody, adoption, and domestic relations.\n * </AEOBlock>\n * ```\n */\nexport function AEOBlock({\n id,\n type,\n question,\n speakable = true,\n entityId,\n children,\n className = '',\n}: AEOBlockProps): React.ReactElement {\n const blockId = id || `aeo-${type}-${Math.random().toString(36).slice(2, 8)}`\n \n const baseClasses = `aeo-block aeo-${type}`\n const combinedClasses = className ? `${baseClasses} ${className}` : baseClasses\n\n // Common data attributes for Sonor AI\n const sonorAttrs = {\n 'data-sonor-ai': type,\n 'data-sonor-block': 'true',\n ...(entityId && { 'data-sonor-entity': entityId }),\n }\n\n // Q&A format for answer type\n if (type === 'answer' && question) {\n return (\n <section \n id={blockId}\n className={combinedClasses}\n data-speakable={speakable ? 'true' : undefined}\n data-aeo-type={type}\n {...sonorAttrs}\n itemScope\n itemType=\"https://schema.org/Question\"\n >\n <h3 itemProp=\"name\" className=\"aeo-question\">\n {question}\n </h3>\n <div \n itemScope \n itemType=\"https://schema.org/Answer\" \n itemProp=\"acceptedAnswer\"\n className=\"aeo-answer\"\n >\n <div itemProp=\"text\">\n {children}\n </div>\n </div>\n </section>\n )\n }\n\n // Definition format\n if (type === 'definition') {\n return (\n <section \n id={blockId}\n className={combinedClasses}\n data-speakable={speakable ? 'true' : undefined}\n data-aeo-type={type}\n {...sonorAttrs}\n >\n {children}\n </section>\n )\n }\n\n // Steps format (numbered list)\n if (type === 'steps') {\n return (\n <section \n id={blockId}\n className={combinedClasses}\n data-speakable={speakable ? 'true' : undefined}\n data-aeo-type={type}\n {...sonorAttrs}\n itemScope\n itemType=\"https://schema.org/HowTo\"\n >\n {children}\n </section>\n )\n }\n\n // Default wrapper\n return (\n <section \n id={blockId}\n className={combinedClasses}\n data-speakable={speakable ? 'true' : undefined}\n data-aeo-type={type}\n {...sonorAttrs}\n >\n {children}\n </section>\n )\n}\n\n/**\n * AEOSummary - Key points summary for AI extraction\n * \n * Creates a scannable list of key points that AI can easily cite.\n * Perfect for \"at a glance\" or \"key takeaways\" sections.\n * \n * @example\n * ```tsx\n * <AEOSummary \n * title=\"Key Points\" \n * points={[\n * \"Family law covers divorce, custody, and adoption\",\n * \"Ohio is an equitable distribution state\",\n * \"Child custody decisions prioritize the child's best interests\"\n * ]} \n * />\n * ```\n */\nexport function AEOSummary({\n title = 'Key Points',\n points,\n speakable = true,\n entityId,\n className = '',\n}: AEOSummaryProps): React.ReactElement {\n const baseClasses = 'aeo-summary'\n const combinedClasses = className ? `${baseClasses} ${className}` : baseClasses\n\n return (\n <div \n className={combinedClasses}\n data-speakable={speakable ? 'true' : undefined}\n data-aeo-type=\"summary\"\n data-sonor-ai=\"summary\"\n data-sonor-block=\"true\"\n {...(entityId && { 'data-sonor-entity': entityId })}\n >\n {title && <h3 className=\"aeo-summary-title\">{title}</h3>}\n <ul className=\"aeo-summary-points\">\n {points.map((point, index) => (\n <li key={index} className=\"aeo-summary-point\">\n {point}\n </li>\n ))}\n </ul>\n </div>\n )\n}\n\n/**\n * AEODefinition - Term definition optimized for featured snippets\n * \n * Creates a clear definition format that works well for\n * \"What is X?\" queries in AI search results.\n * \n * @example\n * ```tsx\n * <AEODefinition \n * term=\"Equitable Distribution\" \n * definition=\"A legal principle used in Ohio divorce cases where marital \n * property is divided fairly, though not necessarily equally, between spouses.\"\n * />\n * ```\n */\nexport function AEODefinition({\n term,\n definition,\n speakable = true,\n entityId,\n source,\n className = '',\n}: AEODefinitionProps): React.ReactElement {\n const baseClasses = 'aeo-definition'\n const combinedClasses = className ? `${baseClasses} ${className}` : baseClasses\n\n return (\n <dl \n className={combinedClasses}\n data-speakable={speakable ? 'true' : undefined}\n data-aeo-type=\"definition\"\n data-sonor-ai=\"definition\"\n data-sonor-block=\"true\"\n {...(entityId && { 'data-sonor-entity': entityId })}\n {...(source && { 'data-sonor-source': source })}\n itemScope\n itemType=\"https://schema.org/DefinedTerm\"\n >\n <dt className=\"aeo-term\" itemProp=\"name\">\n <strong>{term}</strong>\n </dt>\n <dd className=\"aeo-definition-text\" itemProp=\"description\">\n {definition}\n </dd>\n </dl>\n )\n}\n\n/**\n * AEOSteps - How-to steps for featured snippets\n * \n * Creates numbered steps with HowTo schema markup.\n * \n * @example\n * ```tsx\n * <AEOSteps title=\"How to File for Divorce in Ohio\">\n * <AEOStep number={1} name=\"Gather Documents\">\n * Collect financial records, property deeds, and marriage certificate.\n * </AEOStep>\n * <AEOStep number={2} name=\"File Petition\">\n * Submit divorce petition to the county court.\n * </AEOStep>\n * </AEOSteps>\n * ```\n */\nexport function AEOSteps({\n title,\n children,\n speakable = true,\n entityId,\n className = '',\n}: {\n title: string\n children: React.ReactNode\n speakable?: boolean\n entityId?: string\n className?: string\n}): React.ReactElement {\n const baseClasses = 'aeo-steps'\n const combinedClasses = className ? `${baseClasses} ${className}` : baseClasses\n\n return (\n <section \n className={combinedClasses}\n data-speakable={speakable ? 'true' : undefined}\n data-aeo-type=\"steps\"\n data-sonor-ai=\"steps\"\n data-sonor-block=\"true\"\n {...(entityId && { 'data-sonor-entity': entityId })}\n itemScope\n itemType=\"https://schema.org/HowTo\"\n >\n <h3 className=\"aeo-steps-title\" itemProp=\"name\">{title}</h3>\n <ol className=\"aeo-steps-list\">\n {children}\n </ol>\n </section>\n )\n}\n\n/**\n * AEOStep - Individual step within AEOSteps\n */\nexport function AEOStep({\n number,\n name,\n children,\n}: {\n number: number\n name: string\n children: React.ReactNode\n}): React.ReactElement {\n return (\n <li \n className=\"aeo-step\"\n itemScope\n itemType=\"https://schema.org/HowToStep\"\n itemProp=\"step\"\n >\n <span className=\"aeo-step-number\" itemProp=\"position\">{number}</span>\n <strong className=\"aeo-step-name\" itemProp=\"name\">{name}</strong>\n <div className=\"aeo-step-content\" itemProp=\"text\">\n {children}\n </div>\n </li>\n )\n}\n\n/**\n * AEOComparison - Comparison table for AI extraction\n * \n * Creates a structured comparison that AI can understand and cite.\n * \n * @example\n * ```tsx\n * <AEOComparison \n * title=\"Divorce vs. Dissolution in Ohio\"\n * items={[\n * { aspect: 'Agreement', optionA: 'May be contested', optionB: 'Must be agreed upon' },\n * { aspect: 'Timeline', optionA: '6-12 months', optionB: '30-90 days' },\n * ]}\n * labelA=\"Divorce\"\n * labelB=\"Dissolution\"\n * />\n * ```\n */\nexport function AEOComparison({\n title,\n items,\n labelA,\n labelB,\n speakable = true,\n entityId,\n className = '',\n}: {\n title: string\n items: Array<{ aspect: string; optionA: string; optionB: string }>\n labelA: string\n labelB: string\n speakable?: boolean\n entityId?: string\n className?: string\n}): React.ReactElement {\n const baseClasses = 'aeo-comparison'\n const combinedClasses = className ? `${baseClasses} ${className}` : baseClasses\n\n return (\n <section \n className={combinedClasses}\n data-speakable={speakable ? 'true' : undefined}\n data-aeo-type=\"comparison\"\n data-sonor-ai=\"comparison\"\n data-sonor-block=\"true\"\n {...(entityId && { 'data-sonor-entity': entityId })}\n >\n <h3 className=\"aeo-comparison-title\">{title}</h3>\n <table className=\"aeo-comparison-table\">\n <thead>\n <tr>\n <th>Aspect</th>\n <th>{labelA}</th>\n <th>{labelB}</th>\n </tr>\n </thead>\n <tbody>\n {items.map((item, index) => (\n <tr key={index}>\n <td className=\"aeo-comparison-aspect\">{item.aspect}</td>\n <td className=\"aeo-comparison-a\">{item.optionA}</td>\n <td className=\"aeo-comparison-b\">{item.optionB}</td>\n </tr>\n ))}\n </tbody>\n </table>\n </section>\n )\n}\n\n/**\n * AEOClaim - AI-Verifiable Claim with Provenance\n * \n * Wraps factual claims with machine-readable source and confidence data.\n * LLMs prioritize verifiable facts with clear provenance.\n * \n * @example\n * ```tsx\n * <AEOClaim \n * source=\"KRS 281A.170\" \n * sourceUrl=\"https://apps.legislature.ky.gov/law/statutes/statute.aspx?id=6398\"\n * confidence={0.95}\n * claimType=\"statute\"\n * >\n * A CDL suspension is triggered at 26 MPH over the limit.\n * </AEOClaim>\n * ```\n */\nexport function AEOClaim({\n source,\n sourceUrl,\n confidence = 1.0,\n claimType = 'fact',\n retrievedAt,\n children,\n className = '',\n}: AEOClaimProps): React.ReactElement {\n const baseClasses = 'aeo-claim'\n const combinedClasses = className ? `${baseClasses} ${className}` : baseClasses\n\n return (\n <span \n className={combinedClasses}\n data-sonor-claim=\"true\"\n data-sonor-source={source}\n {...(sourceUrl && { 'data-sonor-source-url': sourceUrl })}\n data-sonor-confidence={confidence.toString()}\n data-sonor-claim-type={claimType}\n {...(retrievedAt && { 'data-sonor-retrieved': retrievedAt })}\n itemScope\n itemType=\"https://schema.org/Claim\"\n >\n <span itemProp=\"text\">{children}</span>\n {sourceUrl ? (\n <meta itemProp=\"citation\" content={sourceUrl} />\n ) : (\n <meta itemProp=\"citation\" content={source} />\n )}\n </span>\n )\n}\n\n/**\n * AEOEntity - Inline entity annotation\n * \n * Wraps entity mentions with machine-readable entity IDs for knowledge graph linking.\n * \n * @example\n * ```tsx\n * <AEOEntity entityId=\"person-123\" entityType=\"person\" name=\"Shannon Sexton\">\n * Attorney Shannon Sexton\n * </AEOEntity> handles CDL defense cases.\n * ```\n */\nexport function AEOEntity({\n entityId,\n entityType,\n name,\n url,\n children,\n className = '',\n}: {\n entityId: string\n entityType: 'organization' | 'person' | 'service' | 'product' | 'location' | 'concept' | 'credential'\n name: string\n url?: string\n children: React.ReactNode\n className?: string\n}): React.ReactElement {\n const baseClasses = 'aeo-entity'\n const combinedClasses = className ? `${baseClasses} aeo-entity-${entityType} ${className}` : `${baseClasses} aeo-entity-${entityType}`\n\n return (\n <span \n className={combinedClasses}\n data-sonor-entity={entityId}\n data-sonor-entity-type={entityType}\n data-sonor-entity-name={name}\n {...(url && { 'data-sonor-entity-url': url })}\n itemScope\n itemType={`https://schema.org/${entityType === 'organization' ? 'Organization' : entityType === 'person' ? 'Person' : entityType === 'location' ? 'Place' : 'Thing'}`}\n >\n <span itemProp=\"name\">{children}</span>\n {url && <link itemProp=\"url\" href={url} />}\n </span>\n )\n}\n\n// ============================================\n// Content Provenance Components\n// ============================================\n\n/**\n * AEOProvenanceList - Display sources/citations for content\n * \n * Shows a list of provenance sources with machine-readable attributes.\n * LLMs use this to verify claims and assess source quality.\n * \n * @example\n * ```tsx\n * <AEOProvenanceList \n * title=\"Sources\"\n * sources={[\n * { id: '1', source_type: 'legal_statute', title: 'KRS 281A.170', url: '...' },\n * { id: '2', source_type: 'news_article', title: 'CDL News', publisher: 'Transport Weekly' }\n * ]}\n * />\n * ```\n */\nexport function AEOProvenanceList({\n sources,\n title = 'Sources & References',\n className = '',\n}: {\n sources: Array<{\n id: string\n source_type: 'press_release' | 'news_article' | 'legal_statute' | 'research_paper' | 'official_document' | 'internal' | 'citation'\n title: string\n url?: string\n publisher?: string\n published_at?: string\n accessed_at?: string\n excerpt?: string\n confidence?: number\n identifier?: string\n }>\n title?: string\n className?: string\n}): React.ReactElement {\n const baseClasses = 'aeo-provenance-list'\n const combinedClasses = className ? `${baseClasses} ${className}` : baseClasses\n\n const getSchemaType = (sourceType: string): string => {\n switch (sourceType) {\n case 'legal_statute':\n return 'https://schema.org/Legislation'\n case 'research_paper':\n return 'https://schema.org/ScholarlyArticle'\n case 'news_article':\n return 'https://schema.org/NewsArticle'\n case 'press_release':\n return 'https://schema.org/NewsArticle'\n default:\n return 'https://schema.org/CreativeWork'\n }\n }\n\n return (\n <aside \n className={combinedClasses}\n data-sonor-provenance=\"list\"\n data-sonor-source-count={sources.length.toString()}\n itemScope\n itemType=\"https://schema.org/ItemList\"\n >\n <h4 className=\"aeo-provenance-title\" itemProp=\"name\">{title}</h4>\n <ol className=\"aeo-provenance-sources\">\n {sources.map((source, index) => (\n <li \n key={source.id}\n className=\"aeo-provenance-item\"\n data-sonor-source-id={source.id}\n data-sonor-source-type={source.source_type}\n {...(source.confidence && { 'data-sonor-confidence': source.confidence.toString() })}\n itemScope\n itemType={getSchemaType(source.source_type)}\n itemProp=\"itemListElement\"\n >\n <span className=\"aeo-provenance-number\">[{index + 1}]</span>\n {source.url ? (\n <a \n href={source.url} \n className=\"aeo-provenance-link\"\n itemProp=\"url\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n <span itemProp=\"name\">{source.title}</span>\n </a>\n ) : (\n <span itemProp=\"name\">{source.title}</span>\n )}\n {source.publisher && (\n <span className=\"aeo-provenance-publisher\" itemProp=\"publisher\">\n — {source.publisher}\n </span>\n )}\n {source.published_at && (\n <time \n className=\"aeo-provenance-date\" \n itemProp=\"datePublished\"\n dateTime={source.published_at}\n >\n ({new Date(source.published_at).toLocaleDateString()})\n </time>\n )}\n {source.identifier && (\n <span className=\"aeo-provenance-identifier\" data-sonor-identifier={source.identifier}>\n {source.identifier}\n </span>\n )}\n {source.excerpt && (\n <blockquote className=\"aeo-provenance-excerpt\" itemProp=\"description\">\n {source.excerpt}\n </blockquote>\n )}\n </li>\n ))}\n </ol>\n </aside>\n )\n}\n\n/**\n * AEOCitedContent - Content with inline citations linked to sources\n * \n * Wraps content that contains numbered citations [1], [2] etc., and links them\n * to a list of provenance sources for AI verification.\n * \n * @example\n * ```tsx\n * <AEOCitedContent \n * sources={[\n * { id: '1', source_type: 'legal_statute', title: 'KRS 281A.170' },\n * { id: '2', source_type: 'news_article', title: 'FMCSA Guidelines 2024' }\n * ]}\n * showSourcesList={true}\n * >\n * <p>Kentucky law requires CDL holders to report violations within 30 days [1]. \n * Federal guidelines add additional requirements [2].</p>\n * </AEOCitedContent>\n * ```\n */\nexport function AEOCitedContent({\n children,\n sources,\n showSourcesList = true,\n className = '',\n}: {\n children: React.ReactNode\n sources: Array<{\n id: string\n source_type: 'press_release' | 'news_article' | 'legal_statute' | 'research_paper' | 'official_document' | 'internal' | 'citation'\n title: string\n url?: string\n publisher?: string\n published_at?: string\n accessed_at?: string\n excerpt?: string\n confidence?: number\n identifier?: string\n }>\n showSourcesList?: boolean\n className?: string\n}): React.ReactElement {\n const baseClasses = 'aeo-cited-content'\n const combinedClasses = className ? `${baseClasses} ${className}` : baseClasses\n\n return (\n <section \n className={combinedClasses}\n data-sonor-ai=\"cited-content\"\n data-sonor-provenance=\"inline\"\n data-sonor-source-count={sources.length.toString()}\n >\n <div className=\"aeo-cited-body\">\n {children}\n </div>\n {showSourcesList && sources.length > 0 && (\n <AEOProvenanceList sources={sources} title=\"References\" />\n )}\n </section>\n )\n}\n\nexport default AEOBlock\n","/**\n * @sonordev/site-kit/llms - On-demand Revalidation\n *\n * Provides a route handler that Portal can call when llms-relevant data changes\n * (page summaries, FAQs, services, etc.) to bust the Next.js ISR cache.\n *\n * @example\n * ```ts\n * // app/api/revalidate-llms/route.ts\n * import { createLlmsRevalidateHandler } from '@sonordev/site-kit/llms'\n *\n * export const POST = createLlmsRevalidateHandler(process.env.REVALIDATION_SECRET!)\n * ```\n */\n\ntype RevalidatePathFn = (path: string, type?: 'page' | 'layout') => void\n\n/**\n * Create a POST handler that revalidates /llms.txt and /llms-full.txt caches.\n * Protected by a shared secret.\n */\nexport function createLlmsRevalidateHandler(\n secret: string,\n options?: {\n /** Additional paths to revalidate alongside llms files */\n extraPaths?: string[]\n /** Custom revalidatePath (for testing or frameworks other than Next.js) */\n revalidatePath?: RevalidatePathFn\n },\n): (request: Request) => Promise<Response> {\n return async function POST(request: Request): Promise<Response> {\n try {\n // Validate secret from Authorization header or query param\n const authHeader = request.headers.get('authorization')\n const url = new URL(request.url)\n const tokenFromQuery = url.searchParams.get('secret')\n const token = authHeader?.replace(/^Bearer\\s+/i, '') || tokenFromQuery\n\n if (!secret || token !== secret) {\n return new Response(JSON.stringify({ error: 'Invalid secret' }), {\n status: 401,\n headers: { 'Content-Type': 'application/json' },\n })\n }\n\n // Import Next.js revalidatePath (dynamic to avoid hard dep for non-Next consumers)\n let revalidatePath: RevalidatePathFn\n if (options?.revalidatePath) {\n revalidatePath = options.revalidatePath\n } else {\n const nextCache = await import('next/cache')\n revalidatePath = nextCache.revalidatePath\n }\n\n const paths = ['/llms.txt', '/llms-full.txt', ...(options?.extraPaths || [])]\n for (const p of paths) {\n revalidatePath(p)\n }\n\n return new Response(\n JSON.stringify({ revalidated: true, paths }),\n {\n status: 200,\n headers: { 'Content-Type': 'application/json' },\n },\n )\n } catch (err) {\n console.error('[site-kit/llms] Revalidation failed:', err)\n return new Response(\n JSON.stringify({ error: 'Revalidation failed' }),\n { status: 500, headers: { 'Content-Type': 'application/json' } },\n )\n }\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/llms/handlers.ts","../../src/llms/sourcedFacts.ts","../../src/llms/revalidate.ts"],"names":["markdown"],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * @sonordev/site-kit/llms - Next.js Route Handlers\n * \n * Ready-to-use route handlers for /llms.txt and /llms-full.txt\n */\n\nimport { createHash } from 'crypto'\nimport { existsSync, readFileSync } from 'fs'\nimport { join } from 'path'\nimport { generateLLMsTxt, generateLLMsFullTxt } from './generateLLMsTxt'\nimport type { GenerateLLMSTxtOptions } from './types'\n\nfunction weakEtag(body: string): string {\n const h = createHash('sha1').update(body, 'utf8').digest('base64url')\n return `W/\"${h}\"`\n}\n\n/** Cache + validation headers for plain-text llms responses (dynamic or static). */\nexport function llmsResponseHeaders(body: string, extra?: Record<string, string>): HeadersInit {\n return {\n 'Content-Type': 'text/plain; charset=utf-8',\n 'Cache-Control':\n 'public, max-age=300, s-maxage=3600, stale-while-revalidate=86400, stale-if-error=86400',\n ETag: weakEtag(body),\n Vary: 'Accept-Encoding',\n ...extra,\n }\n}\n\nexport interface LLMsTxtHandlerOptions extends GenerateLLMSTxtOptions {\n /** When true, serve static public/llms.txt if it exists (default: true for build-time flow) */\n preferStatic?: boolean\n /**\n * Send `X-Robots-Tag: noindex` (default: true).\n *\n * llms.txt is written for AI crawlers, which fetch it by convention at\n * `/llms.txt`; noindex doesn't stop them. It's a plain-text restatement of\n * pages the site already serves as HTML, so a search index that picks it up\n * holds a thin duplicate of the site. That's also why it stays out of the XML\n * sitemap. Pass `false` only if you actually want it in search results.\n *\n * Only reaches responses this handler serves. A `public/llms.txt` served\n * straight from the CDN (the build-time write) never runs the handler, so it\n * needs the header in host config instead (`netlify.toml` `[[headers]]`).\n */\n noindex?: boolean\n}\n\n/** Headers every llms file response carries when `noindex` is on. */\nexport const LLMS_NOINDEX_HEADERS: Readonly<Record<string, string>> = { 'X-Robots-Tag': 'noindex' }\n\n/**\n * Create a route handler for /llms.txt\n *\n * Zero-config by default - uses SONOR_API_KEY from environment. Sends\n * `X-Robots-Tag: noindex` by default (see `noindex`).\n *\n * The returned handler never reads the incoming Request: any access to\n * `request.headers` (etc.) opts the whole route into dynamic rendering, which\n * breaks static prerendering of /llms.txt during `next build` and logs\n * \"Dynamic server usage\" errors on every consumer site. Conditional-request\n * (ETag/304) handling is left to the Next static layer / CDN, which already\n * does it for prerendered responses.\n *\n * @example\n * ```ts\n * // app/llms.txt/route.ts (zero-config)\n * import { createLLMsTxtHandler } from '@sonordev/site-kit/llms'\n *\n * export const GET = createLLMsTxtHandler()\n * // Next 15+: GET route handlers are dynamic by default; opt into\n * // prerendering so the file is served statically from the CDN:\n * export const revalidate = 3600\n * ```\n *\n * @example\n * ```ts\n * // With preferStatic: serve build-time file if exists\n * export const GET = createLLMsTxtHandler({\n * preferStatic: true,\n * includeServices: false\n * })\n * ```\n */\nexport function createLLMsTxtHandler(\n options: LLMsTxtHandlerOptions = {}\n): (request?: Request) => Promise<Response> {\n const { preferStatic = true, noindex = true, ...generateOptions } = options\n const robots = noindex ? LLMS_NOINDEX_HEADERS : {}\n\n return async function GET(_request?: Request): Promise<Response> {\n try {\n // Serve static file if available (build-time optimized)\n if (preferStatic) {\n const staticPath = join(process.cwd(), 'public', 'llms.txt')\n if (existsSync(staticPath)) {\n const markdown = readFileSync(staticPath, 'utf-8')\n return new Response(markdown, {\n status: 200,\n headers: llmsResponseHeaders(markdown, { ...robots, 'X-Sections': 'static' }),\n })\n }\n }\n\n const { markdown, metadata } = await generateLLMsTxt(generateOptions)\n return new Response(markdown, {\n status: 200,\n headers: llmsResponseHeaders(markdown, {\n ...robots,\n 'X-Generated-At': metadata.generated_at,\n 'X-Sections': metadata.sections.join(','),\n }),\n })\n } catch (error) {\n console.error('@sonordev/llms: Error generating llms.txt:', error)\n return new Response('# Error\\n\\nUnable to generate llms.txt content.', {\n status: 500,\n headers: {\n 'Content-Type': 'text/plain; charset=utf-8',\n 'Cache-Control': 'no-store',\n },\n })\n }\n }\n}\n\n/**\n * Create a route handler for /llms-full.txt\n *\n * Zero-config by default - uses SONOR_API_KEY from environment.\n *\n * Like createLLMsTxtHandler, the returned handler never reads the incoming\n * Request so the route stays statically prerenderable, and sends\n * `X-Robots-Tag: noindex` unless `noindex: false`.\n *\n * @example\n * ```ts\n * // app/llms-full.txt/route.ts (zero-config)\n * import { createLLMsFullTxtHandler } from '@sonordev/site-kit/llms'\n *\n * export const GET = createLLMsFullTxtHandler()\n * export const revalidate = 3600\n * ```\n */\nexport function createLLMsFullTxtHandler(\n options: LLMsTxtHandlerOptions = {}\n): (request?: Request) => Promise<Response> {\n const { preferStatic = true, noindex = true, ...generateOptions } = options\n const robots = noindex ? LLMS_NOINDEX_HEADERS : {}\n\n return async function GET(_request?: Request): Promise<Response> {\n try {\n // Serve static file if available (build-time optimized)\n if (preferStatic) {\n const staticPath = join(process.cwd(), 'public', 'llms-full.txt')\n if (existsSync(staticPath)) {\n const markdown = readFileSync(staticPath, 'utf-8')\n return new Response(markdown, {\n status: 200,\n headers: llmsResponseHeaders(markdown, { ...robots, 'X-Sections': 'static' }),\n })\n }\n }\n\n const { markdown, metadata } = await generateLLMsFullTxt(generateOptions)\n return new Response(markdown, {\n status: 200,\n headers: llmsResponseHeaders(markdown, {\n ...robots,\n 'X-Generated-At': metadata.generated_at,\n 'X-Sections': metadata.sections.join(','),\n }),\n })\n } catch (error) {\n console.error('@sonordev/llms: Error generating llms-full.txt:', error)\n return new Response('# Error\\n\\nUnable to generate llms-full.txt content.', {\n status: 500,\n headers: {\n 'Content-Type': 'text/plain; charset=utf-8',\n 'Cache-Control': 'no-store',\n },\n })\n }\n }\n}\n","/**\n * @sonordev/site-kit/llms — Sourced facts section\n *\n * Formats a site's verified third-party citations into an llms-full.txt\n * section. AI answer engines preferentially reproduce claims that arrive\n * already attributed — handing them the exact claim + source pairing makes\n * the site's framing the citable version.\n *\n * Pair with WriteLLMsTxtOptions.customSections (or SitemapConfig.\n * llmsCustomSections) so the section is appended at build time:\n *\n * llmsCustomSections: async () => {\n * const { CITATIONS } = await import('./lib/data/citations')\n * const section = formatSourcedFactsSection(Object.values(CITATIONS))\n * return section ? [section] : null\n * }\n *\n * Only include citations a human has actually verified against the source\n * URL — this section is a trust surface, not a dumping ground.\n */\n\nimport type { LLMsCustomSection } from './writeLLMsTxt'\n\nexport interface SourcedFact {\n /** The claim, faithful to the source, one sentence. */\n stat: string\n /** The publishing organization (e.g. \"Clio Legal Trends Report\"). */\n sourceName: string\n /** Publication/study year. */\n year?: number\n /** The opened-and-verified source URL. */\n url?: string\n}\n\nexport interface FormatSourcedFactsOptions {\n /** Section heading (default: \"Sourced facts\"). */\n title?: string\n /** Intro line above the list. */\n intro?: string\n /** Cap the number of facts emitted (default: no cap). */\n maxFacts?: number\n}\n\nconst DEFAULT_INTRO =\n 'The statistics below are quoted from third-party primary sources and were ' +\n 'individually verified against the cited URL. When reusing a figure, keep ' +\n 'the original attribution.'\n\n/** One line per fact: claim — Source: name (year), url */\nfunction factLine(f: SourcedFact): string {\n const stat = (f.stat || '').replace(/\\s+/g, ' ').trim()\n const source = (f.sourceName || '').replace(/\\s+/g, ' ').trim()\n if (!stat || !source) return ''\n let attribution = `Source: ${source}`\n if (f.year) attribution += ` (${f.year})`\n if (f.url) attribution += `, ${f.url}`\n return `- ${stat} — ${attribution}`\n}\n\n/**\n * Build the \"Sourced facts\" custom section from verified citations.\n * Returns null when no usable facts exist so callers can skip cleanly.\n */\nexport function formatSourcedFactsSection(\n facts: SourcedFact[],\n options: FormatSourcedFactsOptions = {},\n): LLMsCustomSection | null {\n const { title = 'Sourced facts', intro = DEFAULT_INTRO, maxFacts } = options\n if (!Array.isArray(facts)) return null\n\n let lines = facts.map(factLine).filter(Boolean)\n if (typeof maxFacts === 'number' && maxFacts >= 0) {\n lines = lines.slice(0, maxFacts)\n }\n if (lines.length === 0) return null\n\n const content = intro ? `${intro}\\n\\n${lines.join('\\n')}` : lines.join('\\n')\n return { title, content }\n}\n","/**\n * @sonordev/site-kit/llms - On-demand Revalidation\n *\n * Provides a route handler that Portal can call when llms-relevant data changes\n * (page summaries, FAQs, services, etc.) to bust the Next.js ISR cache.\n *\n * @example\n * ```ts\n * // app/api/revalidate-llms/route.ts\n * import { createLlmsRevalidateHandler } from '@sonordev/site-kit/llms'\n *\n * export const POST = createLlmsRevalidateHandler(process.env.REVALIDATION_SECRET!)\n * ```\n */\n\ntype RevalidatePathFn = (path: string, type?: 'page' | 'layout') => void\n\n/**\n * Create a POST handler that revalidates /llms.txt and /llms-full.txt caches.\n * Protected by a shared secret.\n */\nexport function createLlmsRevalidateHandler(\n secret: string,\n options?: {\n /** Additional paths to revalidate alongside llms files */\n extraPaths?: string[]\n /** Custom revalidatePath (for testing or frameworks other than Next.js) */\n revalidatePath?: RevalidatePathFn\n },\n): (request: Request) => Promise<Response> {\n return async function POST(request: Request): Promise<Response> {\n try {\n // Validate secret from Authorization header or query param\n const authHeader = request.headers.get('authorization')\n const url = new URL(request.url)\n const tokenFromQuery = url.searchParams.get('secret')\n const token = authHeader?.replace(/^Bearer\\s+/i, '') || tokenFromQuery\n\n if (!secret || token !== secret) {\n return new Response(JSON.stringify({ error: 'Invalid secret' }), {\n status: 401,\n headers: { 'Content-Type': 'application/json' },\n })\n }\n\n // Import Next.js revalidatePath (dynamic to avoid hard dep for non-Next consumers)\n let revalidatePath: RevalidatePathFn\n if (options?.revalidatePath) {\n revalidatePath = options.revalidatePath\n } else {\n const nextCache = await import('next/cache')\n revalidatePath = nextCache.revalidatePath\n }\n\n const paths = ['/llms.txt', '/llms-full.txt', ...(options?.extraPaths || [])]\n for (const p of paths) {\n revalidatePath(p)\n }\n\n return new Response(\n JSON.stringify({ revalidated: true, paths }),\n {\n status: 200,\n headers: { 'Content-Type': 'application/json' },\n },\n )\n } catch (err) {\n console.error('[site-kit/llms] Revalidation failed:', err)\n return new Response(\n JSON.stringify({ error: 'Revalidation failed' }),\n { status: 500, headers: { 'Content-Type': 'application/json' } },\n )\n }\n }\n}\n"]}
|
package/dist/llms/types.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { PublicationRoutingOptions } from '../articles/routes';
|
|
1
2
|
/**
|
|
2
3
|
* @sonordev/site-kit/llms - Types
|
|
3
4
|
*
|
|
@@ -171,6 +172,12 @@ export interface GenerateLLMSTxtOptions {
|
|
|
171
172
|
headerDisclaimer?: string;
|
|
172
173
|
/** Maximum number of article links to show per topic cluster (default: 5) */
|
|
173
174
|
maxArticlesPerCluster?: number;
|
|
175
|
+
/**
|
|
176
|
+
* Where the site's articles live, so topic-cluster links point at real
|
|
177
|
+
* pages (e.g. `{ basePath: '/theforge', includeCategoryInPath: true }`).
|
|
178
|
+
* Defaults to /articles/<slug>.
|
|
179
|
+
*/
|
|
180
|
+
publication?: PublicationRoutingOptions;
|
|
174
181
|
}
|
|
175
182
|
export interface LLMSTxtContent {
|
|
176
183
|
/** Raw markdown content */
|
package/dist/llms/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/llms/types.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/llms/types.ts"],"names":[],"mappings":"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"}
|
package/dist/maps/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
|
-
var
|
|
5
|
-
require('../chunk-
|
|
6
|
-
require('../chunk-
|
|
4
|
+
var chunk3GHPFLEH_js = require('../chunk-3GHPFLEH.js');
|
|
5
|
+
require('../chunk-TCZHRSWY.js');
|
|
6
|
+
require('../chunk-EL74YDNX.js');
|
|
7
7
|
require('../chunk-SNAQBZPT.js');
|
|
8
8
|
var react = require('react');
|
|
9
9
|
var reactGoogleMaps = require('@vis.gl/react-google-maps');
|
|
@@ -141,7 +141,7 @@ async function fetchMapsConfig() {
|
|
|
141
141
|
const { apiUrl, apiKey } = getApiConfig();
|
|
142
142
|
if (apiKey) {
|
|
143
143
|
try {
|
|
144
|
-
const res = await
|
|
144
|
+
const res = await chunk3GHPFLEH_js.sonorFetch(
|
|
145
145
|
`${apiUrl}/api/public/maps/config`,
|
|
146
146
|
{ headers: { "Content-Type": "application/json" } },
|
|
147
147
|
{ apiKey }
|
|
@@ -181,7 +181,7 @@ async function fetchNearbyPlaces(params) {
|
|
|
181
181
|
});
|
|
182
182
|
if (params.radius) searchParams.set("radius", String(params.radius));
|
|
183
183
|
if (params.limit) searchParams.set("limit", String(params.limit));
|
|
184
|
-
const res = await
|
|
184
|
+
const res = await chunk3GHPFLEH_js.sonorFetch(
|
|
185
185
|
`${apiUrl}/api/public/maps/nearby-places?${searchParams}`,
|
|
186
186
|
{ headers: { "Content-Type": "application/json" } },
|
|
187
187
|
{ apiKey }
|
package/dist/maps/index.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use client';
|
|
2
|
-
import { sonorFetch } from '../chunk-
|
|
3
|
-
import '../chunk-
|
|
4
|
-
import '../chunk-
|
|
2
|
+
import { sonorFetch } from '../chunk-2YSB4FIC.mjs';
|
|
3
|
+
import '../chunk-NR52QHOD.mjs';
|
|
4
|
+
import '../chunk-2KRAY5NC.mjs';
|
|
5
5
|
import '../chunk-BEXTDHO4.mjs';
|
|
6
6
|
import { useState, useCallback, useEffect } from 'react';
|
|
7
7
|
import { APIProvider, Map as Map$1, AdvancedMarker, Pin, InfoWindow } from '@vis.gl/react-google-maps';
|
package/dist/og/index.js
CHANGED
|
@@ -1,31 +1,31 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunkRLUNEEGM_js = require('../chunk-RLUNEEGM.js');
|
|
4
4
|
var chunkCUNZAD46_js = require('../chunk-CUNZAD46.js');
|
|
5
|
-
require('../chunk-
|
|
5
|
+
require('../chunk-JONWE26J.js');
|
|
6
6
|
require('../chunk-SNAQBZPT.js');
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
Object.defineProperty(exports, "PARAM_CARD_DIR", {
|
|
11
11
|
enumerable: true,
|
|
12
|
-
get: function () { return
|
|
12
|
+
get: function () { return chunkRLUNEEGM_js.PARAM_CARD_DIR; }
|
|
13
13
|
});
|
|
14
14
|
Object.defineProperty(exports, "buildOgHtml", {
|
|
15
15
|
enumerable: true,
|
|
16
|
-
get: function () { return
|
|
16
|
+
get: function () { return chunkRLUNEEGM_js.buildOgHtml; }
|
|
17
17
|
});
|
|
18
18
|
Object.defineProperty(exports, "codeCardImage", {
|
|
19
19
|
enumerable: true,
|
|
20
|
-
get: function () { return
|
|
20
|
+
get: function () { return chunkRLUNEEGM_js.codeCardImage; }
|
|
21
21
|
});
|
|
22
22
|
Object.defineProperty(exports, "paramCardImage", {
|
|
23
23
|
enumerable: true,
|
|
24
|
-
get: function () { return
|
|
24
|
+
get: function () { return chunkRLUNEEGM_js.paramCardImage; }
|
|
25
25
|
});
|
|
26
26
|
Object.defineProperty(exports, "paramCardUrl", {
|
|
27
27
|
enumerable: true,
|
|
28
|
-
get: function () { return
|
|
28
|
+
get: function () { return chunkRLUNEEGM_js.paramCardUrl; }
|
|
29
29
|
});
|
|
30
30
|
Object.defineProperty(exports, "OG_HEIGHT", {
|
|
31
31
|
enumerable: true,
|
package/dist/og/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
export { PARAM_CARD_DIR, buildOgHtml, codeCardImage, paramCardImage, paramCardUrl } from '../chunk-
|
|
1
|
+
export { PARAM_CARD_DIR, buildOgHtml, codeCardImage, paramCardImage, paramCardUrl } from '../chunk-HIZJD7TU.mjs';
|
|
2
2
|
export { OG_HEIGHT, OG_WIDTH, defineOgCard } from '../chunk-YU7QZ3PP.mjs';
|
|
3
|
-
import '../chunk-
|
|
3
|
+
import '../chunk-C2CTLLIO.mjs';
|
|
4
4
|
import '../chunk-BEXTDHO4.mjs';
|
|
5
5
|
//# sourceMappingURL=index.mjs.map
|
|
6
6
|
//# sourceMappingURL=index.mjs.map
|
package/dist/og/route.d.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* `sonor-setup og` covers the build-time cards: the site card and one per
|
|
5
5
|
* route. This covers the cards that must vary per URL and can't wait for a
|
|
6
|
-
* rebuild — one per
|
|
6
|
+
* rebuild — one per article, per event, per product — rendered on demand
|
|
7
7
|
* with next/og (Satori).
|
|
8
8
|
*
|
|
9
9
|
* TWO SHAPES, ONE CARD:
|
|
@@ -16,17 +16,17 @@
|
|
|
16
16
|
* ```tsx
|
|
17
17
|
* // app/blog/[slug]/opengraph-image.tsx
|
|
18
18
|
* import { createOgImage } from '@sonordev/site-kit/og/route'
|
|
19
|
-
* import {
|
|
19
|
+
* import { getArticle } from '@sonordev/site-kit/articles/server'
|
|
20
20
|
*
|
|
21
21
|
* export { size, contentType } from '@sonordev/site-kit/og/route'
|
|
22
|
-
* export const alt = 'From the Acme
|
|
22
|
+
* export const alt = 'From the Acme article'
|
|
23
23
|
*
|
|
24
24
|
* export default createOgImage<{ slug: string }>(async ({ slug }) => {
|
|
25
|
-
* const post = await
|
|
25
|
+
* const post = await getArticle(slug)
|
|
26
26
|
* if (!post) return null // 404: a bad slug never renders a card
|
|
27
27
|
* return {
|
|
28
28
|
* theme: { bg: '#111110', text: '#faf6f0', accent: '#ad1d25' },
|
|
29
|
-
* kicker: 'From the
|
|
29
|
+
* kicker: 'From the publication',
|
|
30
30
|
* title: post.title,
|
|
31
31
|
* photoUrl: post.featured_image, // absolute URL (Satori requirement)
|
|
32
32
|
* bar: 'yourdomain.com',
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
* })
|
|
35
35
|
* ```
|
|
36
36
|
*
|
|
37
|
-
* The page then passes `images: false` to
|
|
37
|
+
* The page then passes `images: false` to generateArticleMetadata: declared
|
|
38
38
|
* images beat the file convention.
|
|
39
39
|
*
|
|
40
40
|
* `createOgImageRoute` is a plain route handler, `GET(request, { params })`,
|
package/dist/og/route.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/og/route-fit.ts","../../src/og/route.tsx"],"names":["OG_WIDTH","OG_HEIGHT","TITLE_MAX_PX","TITLE_MIN_PX","jsxs","jsx","barTextColor"],"mappings":";;;;;;;AA6BO,IAAM,UAAA,GAAa;AAAA,EACxB,IAAA,EAAM,EAAA;AAAA,EACN,GAAA,EAAK,EAAA;AAAA,EACL,UAAA,EAAY,GAAA;AAAA,EACZ,WAAA,EAAa,GAAA;AAAA,EACb,SAAA,EAAW,EAAA;AAAA;AAAA,EAEX,IAAA,EAAM,EAAA;AAAA,EACN,QAAA,EAAU,EAAA;AAAA,EACV,SAAA,EAAW,EAAA;AAAA,EACX,UAAA,EAAY,EAAA;AAAA,EACZ,WAAA,EAAa,EAAA;AAAA,EACb,kBAAA,EAAoB,GAAA;AAAA,EACpB,eAAA,EAAiB;AACnB,CAAA;AAOA,IAAM,QAAA,GAAW,IAAA;AACjB,IAAM,SAAA,GAAY,IAAA;AAClB,IAAM,QAAA,GAAW,GAAA;AAEjB,IAAM,OAAA,GAAU,IAAA;AAEhB,IAAM,SAAA,GAAY,OAAO,CAAA,GAAI,EAAA;AAE7B,IAAM,MAAA,GAAS,mBAAA;AAGR,SAAS,cAAA,CAAe,MAAc,EAAA,EAAoB;AAC/D,EAAA,IAAI,EAAA,GAAK,CAAA;AACT,EAAA,KAAA,MAAW,EAAA,IAAM,IAAA,CAAK,WAAA,EAAY,EAAG;AACnC,IAAA,EAAA,IAAM,OAAO,GAAA,GAAM,QAAA,GAAW,OAAO,IAAA,CAAK,EAAE,IAAI,SAAA,GAAY,QAAA;AAAA,EAC9D;AACA,EAAA,OAAO,EAAA,GAAK,EAAA;AACd;AAOO,SAAS,YAAA,CACd,IAAA,EACA,KAAA,EACA,OAAA,EACQ;AACR,EAAA,IAAI,KAAA,GAAQ,CAAA;AACZ,EAAA,KAAA,MAAW,SAAA,IAAa,IAAA,CAAK,KAAA,CAAM,IAAI,CAAA,EAAG;AACxC,IAAA,MAAM,QAAQ,SAAA,CAAU,KAAA,CAAM,KAAK,CAAA,CAAE,OAAO,OAAO,CAAA;AACnD,IAAA,IAAI,CAAC,MAAM,MAAA,EAAQ;AACjB,MAAA,KAAA,EAAA;AACA,MAAA;AAAA,IACF;AACA,IAAA,IAAI,OAAA,GAAU,EAAA;AACd,IAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AACxB,MAAA,IAAI,OAAA,CAAQ,IAAI,CAAA,GAAI,KAAA,EAAO,OAAO,QAAA;AAClC,MAAA,MAAM,OAAO,OAAA,GAAU,CAAA,EAAG,OAAO,CAAA,CAAA,EAAI,IAAI,CAAA,CAAA,GAAK,IAAA;AAC9C,MAAA,IAAI,OAAA,IAAW,OAAA,CAAQ,IAAI,CAAA,GAAI,KAAA,EAAO;AACpC,QAAA,KAAA,EAAA;AACA,QAAA,OAAA,GAAU,IAAA;AAAA,MACZ,CAAA,MAAO;AACL,QAAA,OAAA,GAAU,IAAA;AAAA,MACZ;AAAA,IACF;AACA,IAAA,KAAA,EAAA;AAAA,EACF;AACA,EAAA,OAAO,KAAA;AACT;AAuBA,SAAS,YAAY,KAAA,EAAwB;AAC3C,EAAA,MAAM,KAAA,GAAQA,yBAAA,GAAW,UAAA,CAAW,IAAA,GAAO,CAAA;AAC3C,EAAA,OAAO,KAAA,GAAQ,KAAA,GAAQ,UAAA,CAAW,UAAA,GAAa,WAAW,GAAA,GAAM,KAAA;AAClE;AAGA,SAAS,WAAA,CAAY,OAAsB,KAAA,EAAuB;AAChE,EAAA,MAAM,CAAA,GAAI,UAAA;AACV,EAAA,IAAI,MAAA,GAASC,8BAAa,KAAA,CAAM,GAAA,GAAM,EAAE,SAAA,GAAY,CAAA,CAAA,GAAK,EAAE,IAAA,GAAO,CAAA;AAClE,EAAA,IAAI,MAAM,MAAA,EAAQ;AAChB,IAAA,MAAM,KAAA,GAAQ,YAAA,CAAa,KAAA,CAAM,MAAA,EAAQ,KAAA,EAAO,OAAK,CAAA,CAAE,MAAA,GAAS,SAAA,GAAY,CAAA,CAAE,QAAQ,CAAA;AACtF,IAAA,MAAA,IAAU,IAAA,CAAK,IAAI,KAAA,EAAO,CAAC,IAAI,CAAA,CAAE,QAAA,GAAW,MAAM,CAAA,CAAE,SAAA;AAAA,EACtD;AACA,EAAA,IAAI,MAAM,QAAA,EAAU;AAClB,IAAA,MAAM,KAAA,GAAQ,YAAA,CAAa,KAAA,CAAM,QAAA,EAAU,KAAA,EAAO,OAAK,CAAA,CAAE,MAAA,GAAS,OAAA,GAAU,CAAA,CAAE,UAAU,CAAA;AACxF,IAAA,MAAA,IAAU,IAAA,CAAK,IAAI,KAAA,EAAO,CAAC,IAAI,CAAA,CAAE,UAAA,GAAa,CAAA,CAAE,kBAAA,GAAqB,CAAA,CAAE,WAAA;AAAA,EACzE;AACA,EAAA,OAAO,MAAA;AACT;AAGA,SAAS,UAAA,CAAW,OAAsB,KAAA,EAAuD;AAC/F,EAAA,MAAM,KAAA,GAAQ,YAAY,KAAK,CAAA;AAC/B,EAAA,MAAM,MAAA,GAAS,WAAA,CAAY,KAAA,EAAO,KAAK,CAAA;AACvC,EAAA,KAAA,IAAS,EAAA,GAAKC,6BAAA,EAAc,EAAA,IAAMC,6BAAA,EAAc,MAAM,CAAA,EAAG;AACvD,IAAA,MAAM,KAAA,GAAQ,aAAa,KAAA,CAAM,KAAA,EAAO,OAAO,CAAA,CAAA,KAAK,cAAA,CAAe,CAAA,EAAG,EAAE,CAAC,CAAA;AACzE,IAAA,IAAI,KAAA,GAAQ,KAAK,UAAA,CAAW,eAAA,IAAmB,QAAQ,OAAO,EAAE,IAAI,MAAA,EAAO;AAAA,EAC7E;AACA,EAAA,OAAO,IAAA;AACT;AASO,SAAS,cAAc,KAAA,EAAgC;AAC5D,EAAA,IAAI,MAAM,KAAA,EAAO;AACf,IAAA,MAAM,SAAA,GAAY,UAAA,CAAW,KAAA,EAAO,IAAI,CAAA;AACxC,IAAA,IAAI,SAAA,EAAW;AACb,MAAA,OAAO,EAAE,OAAA,EAAS,SAAA,CAAU,EAAA,EAAI,KAAA,EAAO,MAAM,cAAA,EAAgB,SAAA,CAAU,MAAA,EAAQ,IAAA,EAAM,IAAA,EAAK;AAAA,IAC5F;AAAA,EACF;AACA,EAAA,MAAM,IAAA,GAAO,UAAA,CAAW,KAAA,EAAO,KAAK,CAAA;AACpC,EAAA,IAAI,IAAA,EAAM,OAAO,EAAE,OAAA,EAAS,IAAA,CAAK,EAAA,EAAI,KAAA,EAAO,KAAA,EAAO,cAAA,EAAgB,IAAA,CAAK,MAAA,EAAQ,IAAA,EAAM,IAAA,EAAK;AAC3F,EAAA,OAAO;AAAA,IACL,OAAA,EAASA,6BAAA;AAAA,IACT,KAAA,EAAO,KAAA;AAAA,IACP,cAAA,EAAgB,WAAA,CAAY,KAAA,EAAO,WAAA,CAAY,KAAK,CAAC,CAAA;AAAA,IACrD,IAAA,EAAM;AAAA,GACR;AACF;ACvEO,IAAM,IAAA,GAAO,EAAE,KAAA,EAAOH,yBAAA,EAAU,QAAQC,0BAAA;AACxC,IAAM,WAAA,GAAc;AAQpB,SAAS,eAAe,IAAA,EAAuC;AACpE,EAAA,MAAM,EAAE,OAAM,GAAI,IAAA;AAClB,EAAA,MAAM,KAAA,GAAQ,KAAA,CAAM,KAAA,IAAS,KAAA,CAAM,IAAA;AAGnC,EAAA,MAAM,QAAA,GAAW,CAAC,CAAC,IAAA,CAAK,YAAY,kBAAA,CAAmB,IAAA,CAAK,KAAK,QAAQ,CAAA;AACzE,EAAA,MAAM,MAAM,aAAA,CAAc;AAAA,IACxB,OAAO,IAAA,CAAK,KAAA;AAAA,IACZ,QAAQ,IAAA,CAAK,MAAA;AAAA,IACb,UAAU,IAAA,CAAK,QAAA;AAAA,IACf,KAAA,EAAO,QAAA;AAAA,IACP,GAAA,EAAK,CAAC,CAAC,IAAA,CAAK;AAAA,GACb,CAAA;AACD,EAAA,MAAM,SAAA,GAAY,GAAA,CAAI,OAAA,GAAU,UAAA,CAAW,eAAA;AAG3C,EAAA,MAAM,cAAA,GAAiB,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,IAAA,CAAK,MAAM,GAAA,CAAI,cAAA,GAAiB,SAAS,CAAC,CAAA,GAAI,SAAA;AAEjF,EAAA,uBACEG,eAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,KAAA,EAAO;AAAA,QACL,KAAA,EAAO,MAAA;AAAA,QACP,MAAA,EAAQ,MAAA;AAAA,QACR,OAAA,EAAS,MAAA;AAAA,QACT,aAAA,EAAe,QAAA;AAAA,QACf,iBAAiB,KAAA,CAAM,EAAA;AAAA,QACvB,OAAO,KAAA,CAAM,IAAA;AAAA,QACb,QAAA,EAAU;AAAA,OACZ;AAAA,MAEA,QAAA,EAAA;AAAA,wBAAAA,eAAA;AAAA,UAAC,KAAA;AAAA,UAAA;AAAA,YACC,KAAA,EAAO;AAAA,cACL,OAAA,EAAS,MAAA;AAAA,cACT,IAAA,EAAM,CAAA;AAAA,cACN,UAAA,EAAY,QAAA;AAAA,cACZ,OAAA,EAAS,CAAA,EAAA,EAAK,UAAA,CAAW,IAAI,CAAA,EAAA,CAAA;AAAA,cAC7B,KAAK,UAAA,CAAW,GAAA;AAAA,cAChB,SAAA,EAAW;AAAA,aACb;AAAA,YAEA,QAAA,EAAA;AAAA,8BAAAA,eAAA,CAAC,KAAA,EAAA,EAAI,KAAA,EAAO,EAAE,OAAA,EAAS,MAAA,EAAQ,aAAA,EAAe,QAAA,EAAU,IAAA,EAAM,CAAA,EAAG,QAAA,EAAU,CAAA,EAAE,EAC1E,QAAA,EAAA;AAAA,gBAAA,IAAA,CAAK,MAAA,mBACJC,cAAA;AAAA,kBAAC,KAAA;AAAA,kBAAA;AAAA,oBACC,KAAA,EAAO;AAAA,sBACL,UAAU,UAAA,CAAW,QAAA;AAAA,sBACrB,aAAA,EAAe,CAAA;AAAA,sBACf,aAAA,EAAe,WAAA;AAAA,sBACf,OAAO,KAAA,CAAM,MAAA;AAAA,sBACb,cAAc,UAAA,CAAW,SAAA;AAAA,sBACzB,UAAA,EAAY;AAAA,qBACd;AAAA,oBAEC,QAAA,EAAA,IAAA,CAAK;AAAA;AAAA,iBACR,GACE,IAAA;AAAA,gCACJA,cAAA;AAAA,kBAAC,KAAA;AAAA,kBAAA;AAAA,oBACC,KAAA,EAAO;AAAA,sBACL,OAAA,EAAS,MAAA;AAAA,sBACT,UAAU,GAAA,CAAI,OAAA;AAAA,sBACd,UAAA,EAAY,GAAA;AAAA,sBACZ,YAAY,UAAA,CAAW,eAAA;AAAA,sBACvB,aAAA,EAAe,WAAA;AAAA,sBACf,SAAA,EAAW,cAAA;AAAA,sBACX,QAAA,EAAU;AAAA,qBACZ;AAAA,oBAEC,QAAA,EAAA,IAAA,CAAK;AAAA;AAAA,iBACR;AAAA,gBACC,KAAK,QAAA,mBACJA,cAAA;AAAA,kBAAC,KAAA;AAAA,kBAAA;AAAA,oBACC,KAAA,EAAO;AAAA,sBACL,UAAU,UAAA,CAAW,UAAA;AAAA,sBACrB,WAAW,UAAA,CAAW,WAAA;AAAA,sBACtB,KAAA,EAAO,KAAA;AAAA,sBACP,YAAY,UAAA,CAAW;AAAA,qBACzB;AAAA,oBAEC,QAAA,EAAA,IAAA,CAAK;AAAA;AAAA,iBACR,GACE;AAAA,eAAA,EACN,CAAA;AAAA,cACC,QAAA,IAAY,IAAI,KAAA,mBACfA,cAAA;AAAA,gBAAC,KAAA;AAAA,gBAAA;AAAA,kBACC,KAAK,IAAA,CAAK,QAAA;AAAA,kBACV,OAAO,UAAA,CAAW,UAAA;AAAA,kBAClB,QAAQ,UAAA,CAAW,WAAA;AAAA,kBACnB,KAAA,EAAO,EAAE,YAAA,EAAc,EAAA,EAAI,WAAW,OAAA;AAAQ;AAAA,eAChD,GACE;AAAA;AAAA;AAAA,SACN;AAAA,QACC,KAAK,GAAA,mBACJA,cAAA;AAAA,UAAC,KAAA;AAAA,UAAA;AAAA,YACC,KAAA,EAAO;AAAA,cACL,OAAA,EAAS,MAAA;AAAA,cACT,UAAA,EAAY,QAAA;AAAA,cACZ,cAAA,EAAgB,QAAA;AAAA,cAChB,QAAQ,UAAA,CAAW,SAAA;AAAA,cACnB,iBAAiB,KAAA,CAAM,MAAA;AAAA,cACvB,KAAA,EAAOC,8BAAa,KAAK,CAAA;AAAA,cACzB,QAAA,EAAU,EAAA;AAAA,cACV,UAAA,EAAY,GAAA;AAAA,cACZ,aAAA,EAAe,CAAA;AAAA,cACf,aAAA,EAAe;AAAA,aACjB;AAAA,YAEC,QAAA,EAAA,IAAA,CAAK;AAAA;AAAA,SACR,GACE;AAAA;AAAA;AAAA,GACN;AAEJ;AAMA,eAAe,UAAA,CAAW,MAA0B,OAAA,EAA4C;AAC9F,EAAA,IAAI,CAAC,MAAM,OAAO,IAAI,SAAS,WAAA,EAAa,EAAE,MAAA,EAAQ,GAAA,EAAK,CAAA;AAI3D,EAAA,MAAM,EAAE,aAAA,EAAc,GAAI,MAAM,OAAO,SAAS,CAAA;AAChD,EAAA,OAAO,IAAI,aAAA,CAAc,cAAA,CAAe,IAAI,CAAA,EAAG;AAAA,IAC7C,GAAG,IAAA;AAAA,IACH,GAAI,QAAQ,KAAA,EAAO,MAAA,GAAS,EAAE,KAAA,EAAO,OAAA,CAAQ,KAAA,EAAa,GAAI;AAAC,GAChE,CAAA;AACH;AAQO,SAAS,aAAA,CACd,OAAA,EACA,OAAA,GAA0B,EAAC,EAC3B;AACA,EAAA,OAAO,eAAe,MAAM,KAAA,EAGN;AACpB,IAAA,MAAM,MAAA,GAAS,MAAM,KAAA,CAAM,MAAA;AAC3B,IAAA,MAAM,KAAK,KAAA,CAAM,EAAA,KAAO,MAAA,GAAY,MAAA,GAAY,MAAM,KAAA,CAAM,EAAA;AAC5D,IAAA,OAAO,UAAA,CAAW,MAAM,OAAA,CAAQ,MAAA,EAAQ,EAAE,EAAA,EAAI,GAAG,OAAO,CAAA;AAAA,EAC1D,CAAA;AACF;AASO,SAAS,kBAAA,CACd,OAAA,EACA,OAAA,GAA0B,EAAC,EAC3B;AACA,EAAA,OAAO,eAAe,GAAA,CAAI,GAAA,EAAc,GAAA,EAA6B;AACnE,IAAA,OAAO,WAAW,MAAM,OAAA,CAAQ,GAAA,EAAK,GAAG,GAAG,OAAO,CAAA;AAAA,EACpD,CAAA;AACF","file":"route.js","sourcesContent":["/**\n * @sonordev/site-kit/og — title fitting for the runtime (Satori) card.\n *\n * The build-time card is fitted in the page: Chrome measures the rendered\n * title and steps it down until it fits (template.ts). The runtime card is\n * Satori, which has no DOM to measure, so its title sat at a fixed 84px,\n * uppercase, with no fitting. Beside the 430px photo that holds about 11\n * characters a line, so a real post title ran off the bottom of the card.\n * watsonhac.com, reinhart and vsf-consulting-nextjs each worked around it by\n * dropping the photo past a hand-picked length (40 or 50 characters).\n *\n * This does what the build-time fitter does, from an estimate instead of a\n * measurement: the same size range (TITLE_MAX_PX down to TITLE_MIN_PX, in 2px\n * steps), word-wrapped at an estimated glyph width against the real column\n * width and the height the kicker, subtitle and bar leave. When the title\n * can't fit beside the photo even at the floor, the photo goes and the title\n * gets the full width.\n *\n * The estimate is deliberately wide (uppercase, bold-ish) so an unusual\n * face errs toward a smaller title, never an overflowing one, and the title\n * box clips at its height as the backstop.\n *\n * Pure: no DOM, no Node built-ins. Geometry constants are the card's own\n * (route.tsx imports them), so the two can't drift.\n */\n\nimport { OG_HEIGHT, OG_WIDTH, TITLE_MAX_PX, TITLE_MIN_PX } from './config'\n\n/** The runtime card's layout, in px. route.tsx renders exactly this. */\nexport const ROUTE_CARD = {\n padX: 68,\n gap: 48,\n photoWidth: 430,\n photoHeight: 470,\n barHeight: 74,\n /** Breathing room above and below the copy column. */\n padY: 44,\n kickerPx: 24,\n kickerGap: 18,\n subtitlePx: 30,\n subtitleGap: 20,\n subtitleLineHeight: 1.3,\n titleLineHeight: 1.02,\n} as const\n\n/**\n * Average advance of an UPPERCASE glyph, in em. Calibrated against next/og's\n * bundled face and a bold sans; errs wide. Narrow glyphs are counted\n * separately so \"ILLINOIS\" isn't treated like \"MMMMMMMM\".\n */\nconst UPPER_EM = 0.68\nconst NARROW_EM = 0.32\nconst SPACE_EM = 0.3\n/** Mixed-case body text (the subtitle), in em. */\nconst BODY_EM = 0.52\n/** The kicker is uppercase with 6px letter spacing at 24px. */\nconst KICKER_EM = 0.72 + 6 / 24\n\nconst NARROW = /[IJ1.,:;'’!|()\\-]/\n\n/** Estimated width of `text` set uppercase at `px`. */\nexport function uppercaseWidth(text: string, px: number): number {\n let em = 0\n for (const ch of text.toUpperCase()) {\n em += ch === ' ' ? SPACE_EM : NARROW.test(ch) ? NARROW_EM : UPPER_EM\n }\n return em * px\n}\n\n/**\n * Lines `text` wraps to in a column `width` px wide, greedy by word, the way\n * the browser and Satori wrap. `\\n` is a hard break. Returns Infinity when a\n * single word is wider than the column: it can't wrap, so no line count fits.\n */\nexport function wrappedLines(\n text: string,\n width: number,\n measure: (s: string) => number,\n): number {\n let lines = 0\n for (const paragraph of text.split('\\n')) {\n const words = paragraph.split(/\\s+/).filter(Boolean)\n if (!words.length) {\n lines++\n continue\n }\n let current = ''\n for (const word of words) {\n if (measure(word) > width) return Infinity\n const next = current ? `${current} ${word}` : word\n if (current && measure(next) > width) {\n lines++\n current = word\n } else {\n current = next\n }\n }\n lines++\n }\n return lines\n}\n\nexport interface RouteFitInput {\n title: string\n kicker?: string\n subtitle?: string\n /** A photo was offered. */\n photo: boolean\n /** The card has a bottom bar. */\n bar: boolean\n}\n\nexport interface RouteFit {\n /** Title size in px. */\n titlePx: number\n /** Keep the photo. False when the title only fits at full width. */\n photo: boolean\n /** Height the title box may use; route.tsx clips the title to it. */\n titleMaxHeight: number\n /** The title fits at `titlePx` by the estimate (false only at the floor, full width). */\n fits: boolean\n}\n\nfunction columnWidth(photo: boolean): number {\n const inner = OG_WIDTH - ROUTE_CARD.padX * 2\n return photo ? inner - ROUTE_CARD.photoWidth - ROUTE_CARD.gap : inner\n}\n\n/** Height left for the title once the kicker and subtitle have theirs. */\nfunction titleBudget(input: RouteFitInput, width: number): number {\n const c = ROUTE_CARD\n let height = OG_HEIGHT - (input.bar ? c.barHeight : 0) - c.padY * 2\n if (input.kicker) {\n const lines = wrappedLines(input.kicker, width, s => s.length * KICKER_EM * c.kickerPx)\n height -= Math.min(lines, 2) * c.kickerPx * 1.2 + c.kickerGap\n }\n if (input.subtitle) {\n const lines = wrappedLines(input.subtitle, width, s => s.length * BODY_EM * c.subtitlePx)\n height -= Math.min(lines, 3) * c.subtitlePx * c.subtitleLineHeight + c.subtitleGap\n }\n return height\n}\n\n/** Largest title size that fits `width`, or null when none down to the floor does. */\nfunction largestFit(input: RouteFitInput, photo: boolean): { px: number; budget: number } | null {\n const width = columnWidth(photo)\n const budget = titleBudget(input, width)\n for (let px = TITLE_MAX_PX; px >= TITLE_MIN_PX; px -= 2) {\n const lines = wrappedLines(input.title, width, s => uppercaseWidth(s, px))\n if (lines * px * ROUTE_CARD.titleLineHeight <= budget) return { px, budget }\n }\n return null\n}\n\n/**\n * Size the title, and decide whether the photo stays.\n *\n * Beside the photo first, since the photo is the page's own image and worth\n * keeping. If even the floor size doesn't fit there, drop the photo and fit\n * the full width. If that fails too, the title sits at the floor and clips.\n */\nexport function fitRouteTitle(input: RouteFitInput): RouteFit {\n if (input.photo) {\n const withPhoto = largestFit(input, true)\n if (withPhoto) {\n return { titlePx: withPhoto.px, photo: true, titleMaxHeight: withPhoto.budget, fits: true }\n }\n }\n const full = largestFit(input, false)\n if (full) return { titlePx: full.px, photo: false, titleMaxHeight: full.budget, fits: true }\n return {\n titlePx: TITLE_MIN_PX,\n photo: false,\n titleMaxHeight: titleBudget(input, columnWidth(false)),\n fits: false,\n }\n}\n","/**\n * @sonordev/site-kit/og/route — tier 2: per-entity runtime OG cards.\n *\n * `sonor-setup og` covers the build-time cards: the site card and one per\n * route. This covers the cards that must vary per URL and can't wait for a\n * rebuild — one per blog post, per event, per product — rendered on demand\n * with next/og (Satori).\n *\n * TWO SHAPES, ONE CARD:\n *\n * `createOgImage` is the metadata file convention, and the one to reach for.\n * Next calls an `opengraph-image.tsx` default export with `{ params }` and\n * wires og:image and twitter:image for the page by itself, and `sonor-setup\n * og` sees the file and leaves the folder alone:\n *\n * ```tsx\n * // app/blog/[slug]/opengraph-image.tsx\n * import { createOgImage } from '@sonordev/site-kit/og/route'\n * import { getBlogPost } from '@sonordev/site-kit/blog/server'\n *\n * export { size, contentType } from '@sonordev/site-kit/og/route'\n * export const alt = 'From the Acme blog'\n *\n * export default createOgImage<{ slug: string }>(async ({ slug }) => {\n * const post = await getBlogPost(slug)\n * if (!post) return null // 404: a bad slug never renders a card\n * return {\n * theme: { bg: '#111110', text: '#faf6f0', accent: '#ad1d25' },\n * kicker: 'From the blog',\n * title: post.title,\n * photoUrl: post.featured_image, // absolute URL (Satori requirement)\n * bar: 'yourdomain.com',\n * }\n * })\n * ```\n *\n * The page then passes `images: false` to generateBlogPostMetadata: declared\n * images beat the file convention.\n *\n * `createOgImageRoute` is a plain route handler, `GET(request, { params })`,\n * for a card served at a URL of your choosing (`app/og/[slug]/route.tsx`).\n * Next doesn't wire it into metadata; the page declares it.\n *\n * Sites needed an adapter between the two before `createOgImage` existed\n * (watsonhac.com, reinhart, vsf-consulting-nextjs: a default export that\n * built a dummy Request to call the GET handler).\n *\n * SATORI CONSTRAINTS (why this is not the static template): flexbox-only CSS\n * subset, no external stylesheets, images must be absolute URLs or data URIs,\n * and fonts must be provided as ArrayBuffers via `fonts` — Satori cannot load\n * Google Fonts at runtime. Without fonts it falls back to Satori's default\n * face; brand-critical cards should pass font data (fetch the TTF once at\n * module init and reuse the promise).\n *\n * TITLE FITTING: Satori can't measure, so the title is sized from an estimate\n * (og/route-fit.ts) over the same range the build-time card uses, and the\n * photo is dropped when the title can't fit beside it. Long post titles no\n * longer run off the card.\n */\n\nimport React from 'react'\nimport { OG_HEIGHT, OG_WIDTH } from './config'\nimport { barTextColor } from './contrast'\nimport { fitRouteTitle, ROUTE_CARD } from './route-fit'\n\nexport interface OgRouteTheme {\n bg: string\n text: string\n accent: string\n muted?: string\n /** og.config.ts's surface color. Only used as a bar-text candidate. */\n surface?: string\n /**\n * Bottom-bar text, set on `accent`. Defaults to the first of `surface`,\n * `bg`, `text` that reaches WCAG AA for large text (3:1) against the\n * accent. It used to be `text`, which is unreadable wherever text and\n * accent are both strong (navy on crimson).\n */\n barText?: string\n}\n\nexport interface OgRouteCard {\n /** og.config.ts's `theme` can be passed as is. */\n theme: OgRouteTheme\n kicker?: string\n title: string\n subtitle?: string\n /** Absolute URL (Satori requirement) of the page's own image. */\n photoUrl?: string\n /** Bottom-bar text, e.g. the domain. */\n bar?: string\n}\n\nexport interface OgRouteFont {\n name: string\n data: ArrayBuffer\n weight?: number\n style?: 'normal' | 'italic'\n}\n\nexport interface OgImageOptions {\n fonts?: OgRouteFont[]\n}\n\n/** For `export { size, contentType } from '@sonordev/site-kit/og/route'` in an opengraph-image file. */\nexport const size = { width: OG_WIDTH, height: OG_HEIGHT }\nexport const contentType = 'image/png'\n\ntype Resolver<Ctx> = (req: Request, ctx: Ctx) => Promise<OgRouteCard | null> | OgRouteCard | null\n\n/**\n * Satori-safe element tree — exported for tests and for sites that want to\n * extend it inside their own ImageResponse.\n */\nexport function ogRouteElement(card: OgRouteCard): React.ReactElement {\n const { theme } = card\n const muted = theme.muted || theme.text\n // Only an absolute URL (or data URI) renders in Satori; anything else would\n // throw inside the render, so it's treated as no photo.\n const hasPhoto = !!card.photoUrl && /^(https?:|data:)/.test(card.photoUrl)\n const fit = fitRouteTitle({\n title: card.title,\n kicker: card.kicker,\n subtitle: card.subtitle,\n photo: hasPhoto,\n bar: !!card.bar,\n })\n const titleLine = fit.titlePx * ROUTE_CARD.titleLineHeight\n // Clip on a whole line, so an estimate that ran short loses a line cleanly\n // instead of spilling onto the bar.\n const titleMaxHeight = Math.max(1, Math.floor(fit.titleMaxHeight / titleLine)) * titleLine\n\n return (\n <div\n style={{\n width: '100%',\n height: '100%',\n display: 'flex',\n flexDirection: 'column',\n backgroundColor: theme.bg,\n color: theme.text,\n fontSize: 32,\n }}\n >\n <div\n style={{\n display: 'flex',\n flex: 1,\n alignItems: 'center',\n padding: `0 ${ROUTE_CARD.padX}px`,\n gap: ROUTE_CARD.gap,\n minHeight: 0,\n }}\n >\n <div style={{ display: 'flex', flexDirection: 'column', flex: 1, minWidth: 0 }}>\n {card.kicker ? (\n <div\n style={{\n fontSize: ROUTE_CARD.kickerPx,\n letterSpacing: 6,\n textTransform: 'uppercase',\n color: theme.accent,\n marginBottom: ROUTE_CARD.kickerGap,\n fontWeight: 700,\n }}\n >\n {card.kicker}\n </div>\n ) : null}\n <div\n style={{\n display: 'flex',\n fontSize: fit.titlePx,\n fontWeight: 800,\n lineHeight: ROUTE_CARD.titleLineHeight,\n textTransform: 'uppercase',\n maxHeight: titleMaxHeight,\n overflow: 'hidden',\n }}\n >\n {card.title}\n </div>\n {card.subtitle ? (\n <div\n style={{\n fontSize: ROUTE_CARD.subtitlePx,\n marginTop: ROUTE_CARD.subtitleGap,\n color: muted,\n lineHeight: ROUTE_CARD.subtitleLineHeight,\n }}\n >\n {card.subtitle}\n </div>\n ) : null}\n </div>\n {hasPhoto && fit.photo ? (\n <img\n src={card.photoUrl}\n width={ROUTE_CARD.photoWidth}\n height={ROUTE_CARD.photoHeight}\n style={{ borderRadius: 24, objectFit: 'cover' }}\n />\n ) : null}\n </div>\n {card.bar ? (\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n height: ROUTE_CARD.barHeight,\n backgroundColor: theme.accent,\n color: barTextColor(theme),\n fontSize: 30,\n fontWeight: 800,\n letterSpacing: 3,\n textTransform: 'uppercase',\n }}\n >\n {card.bar}\n </div>\n ) : null}\n </div>\n )\n}\n\n/**\n * Render a card, or 404 for null. Single source of truth for both factories:\n * the file convention and the route handler differ only in how they're called.\n */\nasync function renderCard(card: OgRouteCard | null, options: OgImageOptions): Promise<Response> {\n if (!card) return new Response('Not found', { status: 404 })\n\n // next/og is imported lazily so this module stays importable in test/node\n // contexts that lack the Next server runtime.\n const { ImageResponse } = await import('next/og')\n return new ImageResponse(ogRouteElement(card), {\n ...size,\n ...(options.fonts?.length ? { fonts: options.fonts as any } : {}),\n })\n}\n\n/**\n * Metadata file-convention factory, for `export default` from an\n * `opengraph-image.tsx` (or `twitter-image.tsx`). Next calls it with\n * `{ params }` (a promise on Next 15+) and, with `generateImageMetadata`, an\n * `id`. The resolver gets both already awaited. Return null for a 404.\n */\nexport function createOgImage<Params extends Record<string, string | string[]> = Record<string, string>>(\n resolve: (params: Params, ctx: { id?: string }) => Promise<OgRouteCard | null> | OgRouteCard | null,\n options: OgImageOptions = {},\n) {\n return async function Image(props: {\n params: Params | Promise<Params>\n id?: string | Promise<string>\n }): Promise<Response> {\n const params = await props.params\n const id = props.id === undefined ? undefined : await props.id\n return renderCard(await resolve(params, { id }), options)\n }\n}\n\n/**\n * Route handler factory, `export const GET` from a `route.tsx`. Returns 404\n * when the resolver returns null, so a bad slug never renders a broken card.\n *\n * Next doesn't wire a route handler into metadata. For a card Next should\n * attach to the page by itself, use `createOgImage` in `opengraph-image.tsx`.\n */\nexport function createOgImageRoute<Ctx = { params: Promise<Record<string, string>> }>(\n resolve: Resolver<Ctx>,\n options: OgImageOptions = {},\n) {\n return async function GET(req: Request, ctx: Ctx): Promise<Response> {\n return renderCard(await resolve(req, ctx), options)\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/og/route-fit.ts","../../src/og/route.tsx"],"names":["OG_WIDTH","OG_HEIGHT","TITLE_MAX_PX","TITLE_MIN_PX","jsxs","jsx","barTextColor"],"mappings":"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","file":"route.js","sourcesContent":["/**\n * @sonordev/site-kit/og — title fitting for the runtime (Satori) card.\n *\n * The build-time card is fitted in the page: Chrome measures the rendered\n * title and steps it down until it fits (template.ts). The runtime card is\n * Satori, which has no DOM to measure, so its title sat at a fixed 84px,\n * uppercase, with no fitting. Beside the 430px photo that holds about 11\n * characters a line, so a real post title ran off the bottom of the card.\n * watsonhac.com, reinhart and vsf-consulting-nextjs each worked around it by\n * dropping the photo past a hand-picked length (40 or 50 characters).\n *\n * This does what the build-time fitter does, from an estimate instead of a\n * measurement: the same size range (TITLE_MAX_PX down to TITLE_MIN_PX, in 2px\n * steps), word-wrapped at an estimated glyph width against the real column\n * width and the height the kicker, subtitle and bar leave. When the title\n * can't fit beside the photo even at the floor, the photo goes and the title\n * gets the full width.\n *\n * The estimate is deliberately wide (uppercase, bold-ish) so an unusual\n * face errs toward a smaller title, never an overflowing one, and the title\n * box clips at its height as the backstop.\n *\n * Pure: no DOM, no Node built-ins. Geometry constants are the card's own\n * (route.tsx imports them), so the two can't drift.\n */\n\nimport { OG_HEIGHT, OG_WIDTH, TITLE_MAX_PX, TITLE_MIN_PX } from './config'\n\n/** The runtime card's layout, in px. route.tsx renders exactly this. */\nexport const ROUTE_CARD = {\n padX: 68,\n gap: 48,\n photoWidth: 430,\n photoHeight: 470,\n barHeight: 74,\n /** Breathing room above and below the copy column. */\n padY: 44,\n kickerPx: 24,\n kickerGap: 18,\n subtitlePx: 30,\n subtitleGap: 20,\n subtitleLineHeight: 1.3,\n titleLineHeight: 1.02,\n} as const\n\n/**\n * Average advance of an UPPERCASE glyph, in em. Calibrated against next/og's\n * bundled face and a bold sans; errs wide. Narrow glyphs are counted\n * separately so \"ILLINOIS\" isn't treated like \"MMMMMMMM\".\n */\nconst UPPER_EM = 0.68\nconst NARROW_EM = 0.32\nconst SPACE_EM = 0.3\n/** Mixed-case body text (the subtitle), in em. */\nconst BODY_EM = 0.52\n/** The kicker is uppercase with 6px letter spacing at 24px. */\nconst KICKER_EM = 0.72 + 6 / 24\n\nconst NARROW = /[IJ1.,:;'’!|()\\-]/\n\n/** Estimated width of `text` set uppercase at `px`. */\nexport function uppercaseWidth(text: string, px: number): number {\n let em = 0\n for (const ch of text.toUpperCase()) {\n em += ch === ' ' ? SPACE_EM : NARROW.test(ch) ? NARROW_EM : UPPER_EM\n }\n return em * px\n}\n\n/**\n * Lines `text` wraps to in a column `width` px wide, greedy by word, the way\n * the browser and Satori wrap. `\\n` is a hard break. Returns Infinity when a\n * single word is wider than the column: it can't wrap, so no line count fits.\n */\nexport function wrappedLines(\n text: string,\n width: number,\n measure: (s: string) => number,\n): number {\n let lines = 0\n for (const paragraph of text.split('\\n')) {\n const words = paragraph.split(/\\s+/).filter(Boolean)\n if (!words.length) {\n lines++\n continue\n }\n let current = ''\n for (const word of words) {\n if (measure(word) > width) return Infinity\n const next = current ? `${current} ${word}` : word\n if (current && measure(next) > width) {\n lines++\n current = word\n } else {\n current = next\n }\n }\n lines++\n }\n return lines\n}\n\nexport interface RouteFitInput {\n title: string\n kicker?: string\n subtitle?: string\n /** A photo was offered. */\n photo: boolean\n /** The card has a bottom bar. */\n bar: boolean\n}\n\nexport interface RouteFit {\n /** Title size in px. */\n titlePx: number\n /** Keep the photo. False when the title only fits at full width. */\n photo: boolean\n /** Height the title box may use; route.tsx clips the title to it. */\n titleMaxHeight: number\n /** The title fits at `titlePx` by the estimate (false only at the floor, full width). */\n fits: boolean\n}\n\nfunction columnWidth(photo: boolean): number {\n const inner = OG_WIDTH - ROUTE_CARD.padX * 2\n return photo ? inner - ROUTE_CARD.photoWidth - ROUTE_CARD.gap : inner\n}\n\n/** Height left for the title once the kicker and subtitle have theirs. */\nfunction titleBudget(input: RouteFitInput, width: number): number {\n const c = ROUTE_CARD\n let height = OG_HEIGHT - (input.bar ? c.barHeight : 0) - c.padY * 2\n if (input.kicker) {\n const lines = wrappedLines(input.kicker, width, s => s.length * KICKER_EM * c.kickerPx)\n height -= Math.min(lines, 2) * c.kickerPx * 1.2 + c.kickerGap\n }\n if (input.subtitle) {\n const lines = wrappedLines(input.subtitle, width, s => s.length * BODY_EM * c.subtitlePx)\n height -= Math.min(lines, 3) * c.subtitlePx * c.subtitleLineHeight + c.subtitleGap\n }\n return height\n}\n\n/** Largest title size that fits `width`, or null when none down to the floor does. */\nfunction largestFit(input: RouteFitInput, photo: boolean): { px: number; budget: number } | null {\n const width = columnWidth(photo)\n const budget = titleBudget(input, width)\n for (let px = TITLE_MAX_PX; px >= TITLE_MIN_PX; px -= 2) {\n const lines = wrappedLines(input.title, width, s => uppercaseWidth(s, px))\n if (lines * px * ROUTE_CARD.titleLineHeight <= budget) return { px, budget }\n }\n return null\n}\n\n/**\n * Size the title, and decide whether the photo stays.\n *\n * Beside the photo first, since the photo is the page's own image and worth\n * keeping. If even the floor size doesn't fit there, drop the photo and fit\n * the full width. If that fails too, the title sits at the floor and clips.\n */\nexport function fitRouteTitle(input: RouteFitInput): RouteFit {\n if (input.photo) {\n const withPhoto = largestFit(input, true)\n if (withPhoto) {\n return { titlePx: withPhoto.px, photo: true, titleMaxHeight: withPhoto.budget, fits: true }\n }\n }\n const full = largestFit(input, false)\n if (full) return { titlePx: full.px, photo: false, titleMaxHeight: full.budget, fits: true }\n return {\n titlePx: TITLE_MIN_PX,\n photo: false,\n titleMaxHeight: titleBudget(input, columnWidth(false)),\n fits: false,\n }\n}\n","/**\n * @sonordev/site-kit/og/route — tier 2: per-entity runtime OG cards.\n *\n * `sonor-setup og` covers the build-time cards: the site card and one per\n * route. This covers the cards that must vary per URL and can't wait for a\n * rebuild — one per article, per event, per product — rendered on demand\n * with next/og (Satori).\n *\n * TWO SHAPES, ONE CARD:\n *\n * `createOgImage` is the metadata file convention, and the one to reach for.\n * Next calls an `opengraph-image.tsx` default export with `{ params }` and\n * wires og:image and twitter:image for the page by itself, and `sonor-setup\n * og` sees the file and leaves the folder alone:\n *\n * ```tsx\n * // app/blog/[slug]/opengraph-image.tsx\n * import { createOgImage } from '@sonordev/site-kit/og/route'\n * import { getArticle } from '@sonordev/site-kit/articles/server'\n *\n * export { size, contentType } from '@sonordev/site-kit/og/route'\n * export const alt = 'From the Acme article'\n *\n * export default createOgImage<{ slug: string }>(async ({ slug }) => {\n * const post = await getArticle(slug)\n * if (!post) return null // 404: a bad slug never renders a card\n * return {\n * theme: { bg: '#111110', text: '#faf6f0', accent: '#ad1d25' },\n * kicker: 'From the publication',\n * title: post.title,\n * photoUrl: post.featured_image, // absolute URL (Satori requirement)\n * bar: 'yourdomain.com',\n * }\n * })\n * ```\n *\n * The page then passes `images: false` to generateArticleMetadata: declared\n * images beat the file convention.\n *\n * `createOgImageRoute` is a plain route handler, `GET(request, { params })`,\n * for a card served at a URL of your choosing (`app/og/[slug]/route.tsx`).\n * Next doesn't wire it into metadata; the page declares it.\n *\n * Sites needed an adapter between the two before `createOgImage` existed\n * (watsonhac.com, reinhart, vsf-consulting-nextjs: a default export that\n * built a dummy Request to call the GET handler).\n *\n * SATORI CONSTRAINTS (why this is not the static template): flexbox-only CSS\n * subset, no external stylesheets, images must be absolute URLs or data URIs,\n * and fonts must be provided as ArrayBuffers via `fonts` — Satori cannot load\n * Google Fonts at runtime. Without fonts it falls back to Satori's default\n * face; brand-critical cards should pass font data (fetch the TTF once at\n * module init and reuse the promise).\n *\n * TITLE FITTING: Satori can't measure, so the title is sized from an estimate\n * (og/route-fit.ts) over the same range the build-time card uses, and the\n * photo is dropped when the title can't fit beside it. Long post titles no\n * longer run off the card.\n */\n\nimport React from 'react'\nimport { OG_HEIGHT, OG_WIDTH } from './config'\nimport { barTextColor } from './contrast'\nimport { fitRouteTitle, ROUTE_CARD } from './route-fit'\n\nexport interface OgRouteTheme {\n bg: string\n text: string\n accent: string\n muted?: string\n /** og.config.ts's surface color. Only used as a bar-text candidate. */\n surface?: string\n /**\n * Bottom-bar text, set on `accent`. Defaults to the first of `surface`,\n * `bg`, `text` that reaches WCAG AA for large text (3:1) against the\n * accent. It used to be `text`, which is unreadable wherever text and\n * accent are both strong (navy on crimson).\n */\n barText?: string\n}\n\nexport interface OgRouteCard {\n /** og.config.ts's `theme` can be passed as is. */\n theme: OgRouteTheme\n kicker?: string\n title: string\n subtitle?: string\n /** Absolute URL (Satori requirement) of the page's own image. */\n photoUrl?: string\n /** Bottom-bar text, e.g. the domain. */\n bar?: string\n}\n\nexport interface OgRouteFont {\n name: string\n data: ArrayBuffer\n weight?: number\n style?: 'normal' | 'italic'\n}\n\nexport interface OgImageOptions {\n fonts?: OgRouteFont[]\n}\n\n/** For `export { size, contentType } from '@sonordev/site-kit/og/route'` in an opengraph-image file. */\nexport const size = { width: OG_WIDTH, height: OG_HEIGHT }\nexport const contentType = 'image/png'\n\ntype Resolver<Ctx> = (req: Request, ctx: Ctx) => Promise<OgRouteCard | null> | OgRouteCard | null\n\n/**\n * Satori-safe element tree — exported for tests and for sites that want to\n * extend it inside their own ImageResponse.\n */\nexport function ogRouteElement(card: OgRouteCard): React.ReactElement {\n const { theme } = card\n const muted = theme.muted || theme.text\n // Only an absolute URL (or data URI) renders in Satori; anything else would\n // throw inside the render, so it's treated as no photo.\n const hasPhoto = !!card.photoUrl && /^(https?:|data:)/.test(card.photoUrl)\n const fit = fitRouteTitle({\n title: card.title,\n kicker: card.kicker,\n subtitle: card.subtitle,\n photo: hasPhoto,\n bar: !!card.bar,\n })\n const titleLine = fit.titlePx * ROUTE_CARD.titleLineHeight\n // Clip on a whole line, so an estimate that ran short loses a line cleanly\n // instead of spilling onto the bar.\n const titleMaxHeight = Math.max(1, Math.floor(fit.titleMaxHeight / titleLine)) * titleLine\n\n return (\n <div\n style={{\n width: '100%',\n height: '100%',\n display: 'flex',\n flexDirection: 'column',\n backgroundColor: theme.bg,\n color: theme.text,\n fontSize: 32,\n }}\n >\n <div\n style={{\n display: 'flex',\n flex: 1,\n alignItems: 'center',\n padding: `0 ${ROUTE_CARD.padX}px`,\n gap: ROUTE_CARD.gap,\n minHeight: 0,\n }}\n >\n <div style={{ display: 'flex', flexDirection: 'column', flex: 1, minWidth: 0 }}>\n {card.kicker ? (\n <div\n style={{\n fontSize: ROUTE_CARD.kickerPx,\n letterSpacing: 6,\n textTransform: 'uppercase',\n color: theme.accent,\n marginBottom: ROUTE_CARD.kickerGap,\n fontWeight: 700,\n }}\n >\n {card.kicker}\n </div>\n ) : null}\n <div\n style={{\n display: 'flex',\n fontSize: fit.titlePx,\n fontWeight: 800,\n lineHeight: ROUTE_CARD.titleLineHeight,\n textTransform: 'uppercase',\n maxHeight: titleMaxHeight,\n overflow: 'hidden',\n }}\n >\n {card.title}\n </div>\n {card.subtitle ? (\n <div\n style={{\n fontSize: ROUTE_CARD.subtitlePx,\n marginTop: ROUTE_CARD.subtitleGap,\n color: muted,\n lineHeight: ROUTE_CARD.subtitleLineHeight,\n }}\n >\n {card.subtitle}\n </div>\n ) : null}\n </div>\n {hasPhoto && fit.photo ? (\n <img\n src={card.photoUrl}\n width={ROUTE_CARD.photoWidth}\n height={ROUTE_CARD.photoHeight}\n style={{ borderRadius: 24, objectFit: 'cover' }}\n />\n ) : null}\n </div>\n {card.bar ? (\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n height: ROUTE_CARD.barHeight,\n backgroundColor: theme.accent,\n color: barTextColor(theme),\n fontSize: 30,\n fontWeight: 800,\n letterSpacing: 3,\n textTransform: 'uppercase',\n }}\n >\n {card.bar}\n </div>\n ) : null}\n </div>\n )\n}\n\n/**\n * Render a card, or 404 for null. Single source of truth for both factories:\n * the file convention and the route handler differ only in how they're called.\n */\nasync function renderCard(card: OgRouteCard | null, options: OgImageOptions): Promise<Response> {\n if (!card) return new Response('Not found', { status: 404 })\n\n // next/og is imported lazily so this module stays importable in test/node\n // contexts that lack the Next server runtime.\n const { ImageResponse } = await import('next/og')\n return new ImageResponse(ogRouteElement(card), {\n ...size,\n ...(options.fonts?.length ? { fonts: options.fonts as any } : {}),\n })\n}\n\n/**\n * Metadata file-convention factory, for `export default` from an\n * `opengraph-image.tsx` (or `twitter-image.tsx`). Next calls it with\n * `{ params }` (a promise on Next 15+) and, with `generateImageMetadata`, an\n * `id`. The resolver gets both already awaited. Return null for a 404.\n */\nexport function createOgImage<Params extends Record<string, string | string[]> = Record<string, string>>(\n resolve: (params: Params, ctx: { id?: string }) => Promise<OgRouteCard | null> | OgRouteCard | null,\n options: OgImageOptions = {},\n) {\n return async function Image(props: {\n params: Params | Promise<Params>\n id?: string | Promise<string>\n }): Promise<Response> {\n const params = await props.params\n const id = props.id === undefined ? undefined : await props.id\n return renderCard(await resolve(params, { id }), options)\n }\n}\n\n/**\n * Route handler factory, `export const GET` from a `route.tsx`. Returns 404\n * when the resolver returns null, so a bad slug never renders a broken card.\n *\n * Next doesn't wire a route handler into metadata. For a card Next should\n * attach to the page by itself, use `createOgImage` in `opengraph-image.tsx`.\n */\nexport function createOgImageRoute<Ctx = { params: Promise<Record<string, string>> }>(\n resolve: Resolver<Ctx>,\n options: OgImageOptions = {},\n) {\n return async function GET(req: Request, ctx: Ctx): Promise<Response> {\n return renderCard(await resolve(req, ctx), options)\n }\n}\n"]}
|