@ontosdk/next 1.1.0 → 1.3.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.
Files changed (58) hide show
  1. package/JSON_LD_GUIDE.md +403 -0
  2. package/LLMS_TXT_GUIDE.md +297 -0
  3. package/ONTOROVIDER_USAGE.md +130 -0
  4. package/QUICKSTART.md +71 -0
  5. package/README.md +253 -0
  6. package/SCHEMA_QUICKSTART.md +97 -0
  7. package/dist/OntoHead.d.mts +27 -0
  8. package/dist/OntoHead.d.ts +27 -0
  9. package/dist/OntoHead.js +2 -0
  10. package/dist/OntoHead.js.map +1 -0
  11. package/dist/OntoHead.mjs +2 -0
  12. package/dist/OntoHead.mjs.map +1 -0
  13. package/dist/OntoProvider.d.mts +52 -0
  14. package/dist/OntoProvider.d.ts +52 -0
  15. package/dist/OntoProvider.js +2 -0
  16. package/dist/OntoProvider.js.map +1 -0
  17. package/dist/OntoProvider.mjs +2 -0
  18. package/dist/OntoProvider.mjs.map +1 -0
  19. package/dist/cli.js +6 -6
  20. package/dist/cli.js.map +1 -1
  21. package/dist/cli.mjs +6 -6
  22. package/dist/cli.mjs.map +1 -1
  23. package/dist/config.d.mts +85 -0
  24. package/dist/config.d.ts +85 -0
  25. package/dist/config.js +4 -0
  26. package/dist/config.js.map +1 -0
  27. package/dist/config.mjs +4 -0
  28. package/dist/config.mjs.map +1 -0
  29. package/dist/index.d.mts +3 -0
  30. package/dist/index.d.ts +3 -0
  31. package/dist/index.js +6 -4
  32. package/dist/index.js.map +1 -1
  33. package/dist/index.mjs +6 -4
  34. package/dist/index.mjs.map +1 -1
  35. package/dist/middleware.d.mts +21 -1
  36. package/dist/middleware.d.ts +21 -1
  37. package/dist/middleware.js +4 -2
  38. package/dist/middleware.js.map +1 -1
  39. package/dist/middleware.mjs +4 -2
  40. package/dist/middleware.mjs.map +1 -1
  41. package/dist/schemas.d.mts +73 -0
  42. package/dist/schemas.d.ts +73 -0
  43. package/dist/schemas.js +2 -0
  44. package/dist/schemas.js.map +1 -0
  45. package/dist/schemas.mjs +2 -0
  46. package/dist/schemas.mjs.map +1 -0
  47. package/onto.config.example.ts +111 -0
  48. package/package.json +28 -2
  49. package/src/OntoHead.tsx +59 -0
  50. package/src/OntoProvider.tsx +95 -0
  51. package/src/bots.ts +68 -0
  52. package/src/cli.ts +18 -1
  53. package/src/config.ts +151 -0
  54. package/src/index.ts +14 -0
  55. package/src/middleware.ts +82 -24
  56. package/src/schemas.ts +186 -0
  57. package/tsconfig.json +1 -0
  58. package/tsup.config.ts +2 -2
@@ -0,0 +1,73 @@
1
+ import { OntoConfig } from './config.js';
2
+
3
+ /**
4
+ * JSON-LD Schema generators for automatic structured data injection
5
+ * Follows Schema.org standards for AI-friendly metadata
6
+ */
7
+
8
+ /**
9
+ * Standard AIO (AI Optimization) scoring methodology
10
+ * Based on the Onto scoring algorithm:
11
+ * - Content Negotiation: 40% (30 points)
12
+ * - React Tax / Token Efficiency: 35% (30 points)
13
+ * - Structured Data: 25% (25 points)
14
+ * - Semantic HTML: Bonus (15 points)
15
+ */
16
+ interface AIOMethodologySchema {
17
+ '@context': 'https://schema.org';
18
+ '@type': 'HowTo';
19
+ name: string;
20
+ description: string;
21
+ step: Array<{
22
+ '@type': 'HowToStep';
23
+ name: string;
24
+ text: string;
25
+ position: number;
26
+ }>;
27
+ }
28
+ /**
29
+ * Generate AIO Scoring Methodology JSON-LD schema
30
+ * This explains to AI agents how the scoring system works
31
+ */
32
+ declare function generateAIOMethodologySchema(config: OntoConfig, pageUrl: string): AIOMethodologySchema;
33
+ /**
34
+ * Organization schema for About pages
35
+ */
36
+ interface OrganizationSchema {
37
+ '@context': 'https://schema.org';
38
+ '@type': 'Organization';
39
+ name: string;
40
+ url?: string;
41
+ description?: string;
42
+ logo?: string;
43
+ foundingDate?: string;
44
+ }
45
+ /**
46
+ * Generate Organization JSON-LD schema for About pages
47
+ */
48
+ declare function generateOrganizationSchema(config: OntoConfig, pageUrl: string): OrganizationSchema | null;
49
+ /**
50
+ * AboutPage schema combining Organization and WebPage
51
+ */
52
+ interface AboutPageSchema {
53
+ '@context': 'https://schema.org';
54
+ '@type': 'AboutPage';
55
+ name: string;
56
+ url: string;
57
+ description?: string;
58
+ mainEntity?: OrganizationSchema;
59
+ }
60
+ /**
61
+ * Generate AboutPage JSON-LD schema
62
+ */
63
+ declare function generateAboutPageSchema(config: OntoConfig, pageUrl: string): AboutPageSchema;
64
+ /**
65
+ * Determine which schema to generate based on page type
66
+ */
67
+ declare function generateSchemaForPageType(pageType: 'scoring' | 'about' | 'default', config: OntoConfig, pageUrl: string): any | null;
68
+ /**
69
+ * Serialize schema to JSON-LD script tag content
70
+ */
71
+ declare function serializeSchema(schema: any | null): string | null;
72
+
73
+ export { type AIOMethodologySchema, type AboutPageSchema, type OrganizationSchema, generateAIOMethodologySchema, generateAboutPageSchema, generateOrganizationSchema, generateSchemaForPageType, serializeSchema };
@@ -0,0 +1,2 @@
1
+ "use strict";var a=Object.defineProperty;var g=Object.getOwnPropertyDescriptor;var p=Object.getOwnPropertyNames;var u=Object.prototype.hasOwnProperty;var m=(t,e)=>{for(var n in e)a(t,n,{get:e[n],enumerable:!0})},l=(t,e,n,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of p(e))!u.call(t,i)&&i!==n&&a(t,i,{get:()=>e[i],enumerable:!(o=g(e,i))||o.enumerable});return t};var h=t=>l(a({},"__esModule",{value:!0}),t);var y={};m(y,{generateAIOMethodologySchema:()=>r,generateAboutPageSchema:()=>c,generateOrganizationSchema:()=>s,generateSchemaForPageType:()=>f,serializeSchema:()=>d});module.exports=h(y);function r(t,e){return{"@context":"https://schema.org","@type":"HowTo",name:"AIO Score Calculation Methodology",description:"AI Optimization (AIO) Score measures how well a website is optimized for AI agents and LLM crawlers. Scored out of 100 points based on four key metrics.",step:[{"@type":"HowToStep",name:"Content Negotiation",text:"Check if the site responds to Accept: text/markdown header. Weight: 40%. Penalty: -30 points if missing. This ensures AI bots receive optimized content instead of heavy HTML.",position:1},{"@type":"HowToStep",name:"Token Efficiency (React Tax)",text:"Measure the ratio of visible text to total HTML size. Weight: 35%. Penalty: -30 points if HTML > 100KB but text < 1KB. Detects JavaScript-heavy sites that are difficult for AI to parse.",position:2},{"@type":"HowToStep",name:"Structured Data",text:"Verify presence of JSON-LD structured data (Schema.org). Weight: 25%. Penalty: -25 points if missing. Enables AI to confidently extract pricing, products, and entities.",position:3},{"@type":"HowToStep",name:"Semantic HTML",text:"Check for semantic tags like <main> and <article>. Bonus: +15 points if present. Helps AI agents separate navigation from core content.",position:4}]}}function s(t,e){if(!t.organization)return null;let n={"@context":"https://schema.org","@type":"Organization",name:t.organization.name};return t.organization.url&&(n.url=t.organization.url),t.organization.description&&(n.description=t.organization.description),t.organization.logo&&(n.logo=t.organization.logo),t.organization.foundingDate&&(n.foundingDate=t.organization.foundingDate),n}function c(t,e){let n=s(t,e),o={"@context":"https://schema.org","@type":"AboutPage",name:`About ${t.name}`,url:e};return t.summary&&(o.description=t.summary),n&&(o.mainEntity=n),o}function f(t,e,n){switch(t){case"scoring":return r(e,n);case"about":return c(e,n);default:return null}}function d(t){return t?JSON.stringify(t,null,2):null}0&&(module.exports={generateAIOMethodologySchema,generateAboutPageSchema,generateOrganizationSchema,generateSchemaForPageType,serializeSchema});
2
+ //# sourceMappingURL=schemas.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/schemas.ts"],"sourcesContent":["/**\r\n * JSON-LD Schema generators for automatic structured data injection\r\n * Follows Schema.org standards for AI-friendly metadata\r\n */\r\n\r\nimport { OntoConfig } from './config';\r\n\r\n/**\r\n * Standard AIO (AI Optimization) scoring methodology\r\n * Based on the Onto scoring algorithm:\r\n * - Content Negotiation: 40% (30 points)\r\n * - React Tax / Token Efficiency: 35% (30 points)\r\n * - Structured Data: 25% (25 points)\r\n * - Semantic HTML: Bonus (15 points)\r\n */\r\nexport interface AIOMethodologySchema {\r\n '@context': 'https://schema.org';\r\n '@type': 'HowTo';\r\n name: string;\r\n description: string;\r\n step: Array<{\r\n '@type': 'HowToStep';\r\n name: string;\r\n text: string;\r\n position: number;\r\n }>;\r\n}\r\n\r\n/**\r\n * Generate AIO Scoring Methodology JSON-LD schema\r\n * This explains to AI agents how the scoring system works\r\n */\r\nexport function generateAIOMethodologySchema(\r\n config: OntoConfig,\r\n pageUrl: string\r\n): AIOMethodologySchema {\r\n return {\r\n '@context': 'https://schema.org',\r\n '@type': 'HowTo',\r\n name: 'AIO Score Calculation Methodology',\r\n description: 'AI Optimization (AIO) Score measures how well a website is optimized for AI agents and LLM crawlers. Scored out of 100 points based on four key metrics.',\r\n step: [\r\n {\r\n '@type': 'HowToStep',\r\n name: 'Content Negotiation',\r\n text: 'Check if the site responds to Accept: text/markdown header. Weight: 40%. Penalty: -30 points if missing. This ensures AI bots receive optimized content instead of heavy HTML.',\r\n position: 1\r\n },\r\n {\r\n '@type': 'HowToStep',\r\n name: 'Token Efficiency (React Tax)',\r\n text: 'Measure the ratio of visible text to total HTML size. Weight: 35%. Penalty: -30 points if HTML > 100KB but text < 1KB. Detects JavaScript-heavy sites that are difficult for AI to parse.',\r\n position: 2\r\n },\r\n {\r\n '@type': 'HowToStep',\r\n name: 'Structured Data',\r\n text: 'Verify presence of JSON-LD structured data (Schema.org). Weight: 25%. Penalty: -25 points if missing. Enables AI to confidently extract pricing, products, and entities.',\r\n position: 3\r\n },\r\n {\r\n '@type': 'HowToStep',\r\n name: 'Semantic HTML',\r\n text: 'Check for semantic tags like <main> and <article>. Bonus: +15 points if present. Helps AI agents separate navigation from core content.',\r\n position: 4\r\n }\r\n ]\r\n };\r\n}\r\n\r\n/**\r\n * Organization schema for About pages\r\n */\r\nexport interface OrganizationSchema {\r\n '@context': 'https://schema.org';\r\n '@type': 'Organization';\r\n name: string;\r\n url?: string;\r\n description?: string;\r\n logo?: string;\r\n foundingDate?: string;\r\n}\r\n\r\n/**\r\n * Generate Organization JSON-LD schema for About pages\r\n */\r\nexport function generateOrganizationSchema(\r\n config: OntoConfig,\r\n pageUrl: string\r\n): OrganizationSchema | null {\r\n if (!config.organization) {\r\n return null;\r\n }\r\n\r\n const schema: OrganizationSchema = {\r\n '@context': 'https://schema.org',\r\n '@type': 'Organization',\r\n name: config.organization.name\r\n };\r\n\r\n if (config.organization.url) {\r\n schema.url = config.organization.url;\r\n }\r\n\r\n if (config.organization.description) {\r\n schema.description = config.organization.description;\r\n }\r\n\r\n if (config.organization.logo) {\r\n schema.logo = config.organization.logo;\r\n }\r\n\r\n if (config.organization.foundingDate) {\r\n schema.foundingDate = config.organization.foundingDate;\r\n }\r\n\r\n return schema;\r\n}\r\n\r\n/**\r\n * AboutPage schema combining Organization and WebPage\r\n */\r\nexport interface AboutPageSchema {\r\n '@context': 'https://schema.org';\r\n '@type': 'AboutPage';\r\n name: string;\r\n url: string;\r\n description?: string;\r\n mainEntity?: OrganizationSchema;\r\n}\r\n\r\n/**\r\n * Generate AboutPage JSON-LD schema\r\n */\r\nexport function generateAboutPageSchema(\r\n config: OntoConfig,\r\n pageUrl: string\r\n): AboutPageSchema {\r\n const orgSchema = generateOrganizationSchema(config, pageUrl);\r\n\r\n const schema: AboutPageSchema = {\r\n '@context': 'https://schema.org',\r\n '@type': 'AboutPage',\r\n name: `About ${config.name}`,\r\n url: pageUrl\r\n };\r\n\r\n if (config.summary) {\r\n schema.description = config.summary;\r\n }\r\n\r\n if (orgSchema) {\r\n schema.mainEntity = orgSchema;\r\n }\r\n\r\n return schema;\r\n}\r\n\r\n/**\r\n * Determine which schema to generate based on page type\r\n */\r\nexport function generateSchemaForPageType(\r\n pageType: 'scoring' | 'about' | 'default',\r\n config: OntoConfig,\r\n pageUrl: string\r\n): any | null {\r\n switch (pageType) {\r\n case 'scoring':\r\n return generateAIOMethodologySchema(config, pageUrl);\r\n case 'about':\r\n return generateAboutPageSchema(config, pageUrl);\r\n case 'default':\r\n default:\r\n return null;\r\n }\r\n}\r\n\r\n/**\r\n * Serialize schema to JSON-LD script tag content\r\n */\r\nexport function serializeSchema(schema: any | null): string | null {\r\n if (!schema) {\r\n return null;\r\n }\r\n return JSON.stringify(schema, null, 2);\r\n}\r\n"],"mappings":"yaAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,kCAAAE,EAAA,4BAAAC,EAAA,+BAAAC,EAAA,8BAAAC,EAAA,oBAAAC,IAAA,eAAAC,EAAAP,GAgCO,SAASE,EACdM,EACAC,EACsB,CACtB,MAAO,CACL,WAAY,qBACZ,QAAS,QACT,KAAM,oCACN,YAAa,2JACb,KAAM,CACJ,CACE,QAAS,YACT,KAAM,sBACN,KAAM,iLACN,SAAU,CACZ,EACA,CACE,QAAS,YACT,KAAM,+BACN,KAAM,4LACN,SAAU,CACZ,EACA,CACE,QAAS,YACT,KAAM,kBACN,KAAM,2KACN,SAAU,CACZ,EACA,CACE,QAAS,YACT,KAAM,gBACN,KAAM,0IACN,SAAU,CACZ,CACF,CACF,CACF,CAkBO,SAASL,EACdI,EACAC,EAC2B,CAC3B,GAAI,CAACD,EAAO,aACV,OAAO,KAGT,IAAME,EAA6B,CACjC,WAAY,qBACZ,QAAS,eACT,KAAMF,EAAO,aAAa,IAC5B,EAEA,OAAIA,EAAO,aAAa,MACtBE,EAAO,IAAMF,EAAO,aAAa,KAG/BA,EAAO,aAAa,cACtBE,EAAO,YAAcF,EAAO,aAAa,aAGvCA,EAAO,aAAa,OACtBE,EAAO,KAAOF,EAAO,aAAa,MAGhCA,EAAO,aAAa,eACtBE,EAAO,aAAeF,EAAO,aAAa,cAGrCE,CACT,CAiBO,SAASP,EACdK,EACAC,EACiB,CACjB,IAAME,EAAYP,EAA2BI,EAAQC,CAAO,EAEtDC,EAA0B,CAC9B,WAAY,qBACZ,QAAS,YACT,KAAM,SAASF,EAAO,IAAI,GAC1B,IAAKC,CACP,EAEA,OAAID,EAAO,UACTE,EAAO,YAAcF,EAAO,SAG1BG,IACFD,EAAO,WAAaC,GAGfD,CACT,CAKO,SAASL,EACdO,EACAJ,EACAC,EACY,CACZ,OAAQG,EAAU,CAChB,IAAK,UACH,OAAOV,EAA6BM,EAAQC,CAAO,EACrD,IAAK,QACH,OAAON,EAAwBK,EAAQC,CAAO,EAEhD,QACE,OAAO,IACX,CACF,CAKO,SAASH,EAAgBI,EAAmC,CACjE,OAAKA,EAGE,KAAK,UAAUA,EAAQ,KAAM,CAAC,EAF5B,IAGX","names":["schemas_exports","__export","generateAIOMethodologySchema","generateAboutPageSchema","generateOrganizationSchema","generateSchemaForPageType","serializeSchema","__toCommonJS","config","pageUrl","schema","orgSchema","pageType"]}
@@ -0,0 +1,2 @@
1
+ function i(t,n){return{"@context":"https://schema.org","@type":"HowTo",name:"AIO Score Calculation Methodology",description:"AI Optimization (AIO) Score measures how well a website is optimized for AI agents and LLM crawlers. Scored out of 100 points based on four key metrics.",step:[{"@type":"HowToStep",name:"Content Negotiation",text:"Check if the site responds to Accept: text/markdown header. Weight: 40%. Penalty: -30 points if missing. This ensures AI bots receive optimized content instead of heavy HTML.",position:1},{"@type":"HowToStep",name:"Token Efficiency (React Tax)",text:"Measure the ratio of visible text to total HTML size. Weight: 35%. Penalty: -30 points if HTML > 100KB but text < 1KB. Detects JavaScript-heavy sites that are difficult for AI to parse.",position:2},{"@type":"HowToStep",name:"Structured Data",text:"Verify presence of JSON-LD structured data (Schema.org). Weight: 25%. Penalty: -25 points if missing. Enables AI to confidently extract pricing, products, and entities.",position:3},{"@type":"HowToStep",name:"Semantic HTML",text:"Check for semantic tags like <main> and <article>. Bonus: +15 points if present. Helps AI agents separate navigation from core content.",position:4}]}}function a(t,n){if(!t.organization)return null;let e={"@context":"https://schema.org","@type":"Organization",name:t.organization.name};return t.organization.url&&(e.url=t.organization.url),t.organization.description&&(e.description=t.organization.description),t.organization.logo&&(e.logo=t.organization.logo),t.organization.foundingDate&&(e.foundingDate=t.organization.foundingDate),e}function r(t,n){let e=a(t,n),o={"@context":"https://schema.org","@type":"AboutPage",name:`About ${t.name}`,url:n};return t.summary&&(o.description=t.summary),e&&(o.mainEntity=e),o}function s(t,n,e){switch(t){case"scoring":return i(n,e);case"about":return r(n,e);default:return null}}function c(t){return t?JSON.stringify(t,null,2):null}export{i as generateAIOMethodologySchema,r as generateAboutPageSchema,a as generateOrganizationSchema,s as generateSchemaForPageType,c as serializeSchema};
2
+ //# sourceMappingURL=schemas.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/schemas.ts"],"sourcesContent":["/**\r\n * JSON-LD Schema generators for automatic structured data injection\r\n * Follows Schema.org standards for AI-friendly metadata\r\n */\r\n\r\nimport { OntoConfig } from './config';\r\n\r\n/**\r\n * Standard AIO (AI Optimization) scoring methodology\r\n * Based on the Onto scoring algorithm:\r\n * - Content Negotiation: 40% (30 points)\r\n * - React Tax / Token Efficiency: 35% (30 points)\r\n * - Structured Data: 25% (25 points)\r\n * - Semantic HTML: Bonus (15 points)\r\n */\r\nexport interface AIOMethodologySchema {\r\n '@context': 'https://schema.org';\r\n '@type': 'HowTo';\r\n name: string;\r\n description: string;\r\n step: Array<{\r\n '@type': 'HowToStep';\r\n name: string;\r\n text: string;\r\n position: number;\r\n }>;\r\n}\r\n\r\n/**\r\n * Generate AIO Scoring Methodology JSON-LD schema\r\n * This explains to AI agents how the scoring system works\r\n */\r\nexport function generateAIOMethodologySchema(\r\n config: OntoConfig,\r\n pageUrl: string\r\n): AIOMethodologySchema {\r\n return {\r\n '@context': 'https://schema.org',\r\n '@type': 'HowTo',\r\n name: 'AIO Score Calculation Methodology',\r\n description: 'AI Optimization (AIO) Score measures how well a website is optimized for AI agents and LLM crawlers. Scored out of 100 points based on four key metrics.',\r\n step: [\r\n {\r\n '@type': 'HowToStep',\r\n name: 'Content Negotiation',\r\n text: 'Check if the site responds to Accept: text/markdown header. Weight: 40%. Penalty: -30 points if missing. This ensures AI bots receive optimized content instead of heavy HTML.',\r\n position: 1\r\n },\r\n {\r\n '@type': 'HowToStep',\r\n name: 'Token Efficiency (React Tax)',\r\n text: 'Measure the ratio of visible text to total HTML size. Weight: 35%. Penalty: -30 points if HTML > 100KB but text < 1KB. Detects JavaScript-heavy sites that are difficult for AI to parse.',\r\n position: 2\r\n },\r\n {\r\n '@type': 'HowToStep',\r\n name: 'Structured Data',\r\n text: 'Verify presence of JSON-LD structured data (Schema.org). Weight: 25%. Penalty: -25 points if missing. Enables AI to confidently extract pricing, products, and entities.',\r\n position: 3\r\n },\r\n {\r\n '@type': 'HowToStep',\r\n name: 'Semantic HTML',\r\n text: 'Check for semantic tags like <main> and <article>. Bonus: +15 points if present. Helps AI agents separate navigation from core content.',\r\n position: 4\r\n }\r\n ]\r\n };\r\n}\r\n\r\n/**\r\n * Organization schema for About pages\r\n */\r\nexport interface OrganizationSchema {\r\n '@context': 'https://schema.org';\r\n '@type': 'Organization';\r\n name: string;\r\n url?: string;\r\n description?: string;\r\n logo?: string;\r\n foundingDate?: string;\r\n}\r\n\r\n/**\r\n * Generate Organization JSON-LD schema for About pages\r\n */\r\nexport function generateOrganizationSchema(\r\n config: OntoConfig,\r\n pageUrl: string\r\n): OrganizationSchema | null {\r\n if (!config.organization) {\r\n return null;\r\n }\r\n\r\n const schema: OrganizationSchema = {\r\n '@context': 'https://schema.org',\r\n '@type': 'Organization',\r\n name: config.organization.name\r\n };\r\n\r\n if (config.organization.url) {\r\n schema.url = config.organization.url;\r\n }\r\n\r\n if (config.organization.description) {\r\n schema.description = config.organization.description;\r\n }\r\n\r\n if (config.organization.logo) {\r\n schema.logo = config.organization.logo;\r\n }\r\n\r\n if (config.organization.foundingDate) {\r\n schema.foundingDate = config.organization.foundingDate;\r\n }\r\n\r\n return schema;\r\n}\r\n\r\n/**\r\n * AboutPage schema combining Organization and WebPage\r\n */\r\nexport interface AboutPageSchema {\r\n '@context': 'https://schema.org';\r\n '@type': 'AboutPage';\r\n name: string;\r\n url: string;\r\n description?: string;\r\n mainEntity?: OrganizationSchema;\r\n}\r\n\r\n/**\r\n * Generate AboutPage JSON-LD schema\r\n */\r\nexport function generateAboutPageSchema(\r\n config: OntoConfig,\r\n pageUrl: string\r\n): AboutPageSchema {\r\n const orgSchema = generateOrganizationSchema(config, pageUrl);\r\n\r\n const schema: AboutPageSchema = {\r\n '@context': 'https://schema.org',\r\n '@type': 'AboutPage',\r\n name: `About ${config.name}`,\r\n url: pageUrl\r\n };\r\n\r\n if (config.summary) {\r\n schema.description = config.summary;\r\n }\r\n\r\n if (orgSchema) {\r\n schema.mainEntity = orgSchema;\r\n }\r\n\r\n return schema;\r\n}\r\n\r\n/**\r\n * Determine which schema to generate based on page type\r\n */\r\nexport function generateSchemaForPageType(\r\n pageType: 'scoring' | 'about' | 'default',\r\n config: OntoConfig,\r\n pageUrl: string\r\n): any | null {\r\n switch (pageType) {\r\n case 'scoring':\r\n return generateAIOMethodologySchema(config, pageUrl);\r\n case 'about':\r\n return generateAboutPageSchema(config, pageUrl);\r\n case 'default':\r\n default:\r\n return null;\r\n }\r\n}\r\n\r\n/**\r\n * Serialize schema to JSON-LD script tag content\r\n */\r\nexport function serializeSchema(schema: any | null): string | null {\r\n if (!schema) {\r\n return null;\r\n }\r\n return JSON.stringify(schema, null, 2);\r\n}\r\n"],"mappings":"AAgCO,SAASA,EACdC,EACAC,EACsB,CACtB,MAAO,CACL,WAAY,qBACZ,QAAS,QACT,KAAM,oCACN,YAAa,2JACb,KAAM,CACJ,CACE,QAAS,YACT,KAAM,sBACN,KAAM,iLACN,SAAU,CACZ,EACA,CACE,QAAS,YACT,KAAM,+BACN,KAAM,4LACN,SAAU,CACZ,EACA,CACE,QAAS,YACT,KAAM,kBACN,KAAM,2KACN,SAAU,CACZ,EACA,CACE,QAAS,YACT,KAAM,gBACN,KAAM,0IACN,SAAU,CACZ,CACF,CACF,CACF,CAkBO,SAASC,EACdF,EACAC,EAC2B,CAC3B,GAAI,CAACD,EAAO,aACV,OAAO,KAGT,IAAMG,EAA6B,CACjC,WAAY,qBACZ,QAAS,eACT,KAAMH,EAAO,aAAa,IAC5B,EAEA,OAAIA,EAAO,aAAa,MACtBG,EAAO,IAAMH,EAAO,aAAa,KAG/BA,EAAO,aAAa,cACtBG,EAAO,YAAcH,EAAO,aAAa,aAGvCA,EAAO,aAAa,OACtBG,EAAO,KAAOH,EAAO,aAAa,MAGhCA,EAAO,aAAa,eACtBG,EAAO,aAAeH,EAAO,aAAa,cAGrCG,CACT,CAiBO,SAASC,EACdJ,EACAC,EACiB,CACjB,IAAMI,EAAYH,EAA2BF,EAAQC,CAAO,EAEtDE,EAA0B,CAC9B,WAAY,qBACZ,QAAS,YACT,KAAM,SAASH,EAAO,IAAI,GAC1B,IAAKC,CACP,EAEA,OAAID,EAAO,UACTG,EAAO,YAAcH,EAAO,SAG1BK,IACFF,EAAO,WAAaE,GAGfF,CACT,CAKO,SAASG,EACdC,EACAP,EACAC,EACY,CACZ,OAAQM,EAAU,CAChB,IAAK,UACH,OAAOR,EAA6BC,EAAQC,CAAO,EACrD,IAAK,QACH,OAAOG,EAAwBJ,EAAQC,CAAO,EAEhD,QACE,OAAO,IACX,CACF,CAKO,SAASO,EAAgBL,EAAmC,CACjE,OAAKA,EAGE,KAAK,UAAUA,EAAQ,KAAM,CAAC,EAF5B,IAGX","names":["generateAIOMethodologySchema","config","pageUrl","generateOrganizationSchema","schema","generateAboutPageSchema","orgSchema","generateSchemaForPageType","pageType","serializeSchema"]}
@@ -0,0 +1,111 @@
1
+ import { OntoConfig } from './src/config';
2
+
3
+ /**
4
+ * Example onto.config.ts file
5
+ *
6
+ * Place this file in your project root as `onto.config.ts` to enable
7
+ * dynamic llms.txt generation.
8
+ *
9
+ * The middleware will automatically read this config and generate
10
+ * /llms.txt on the fly when AI agents request it.
11
+ */
12
+ const config: OntoConfig = {
13
+ // Required: The name of your project/site
14
+ name: 'My Awesome Project',
15
+
16
+ // Required: A concise summary for AI agents
17
+ summary: 'A modern web application for managing tasks and projects. Built with Next.js, TypeScript, and React. Provides a RESTful API and interactive UI.',
18
+
19
+ // Required: Base URL of your site
20
+ baseUrl: 'https://example.com',
21
+
22
+ // Optional: Key routes that AI agents should know about
23
+ routes: [
24
+ {
25
+ path: '/',
26
+ description: 'Homepage with product overview and key features',
27
+ pageType: 'default'
28
+ },
29
+ {
30
+ path: '/score',
31
+ description: 'AIO Score Calculator - check your AI optimization score',
32
+ pageType: 'scoring' // Automatically injects Methodology JSON-LD schema
33
+ },
34
+ {
35
+ path: '/about',
36
+ description: 'About our company and mission',
37
+ pageType: 'about' // Automatically injects Organization/AboutPage JSON-LD schema
38
+ },
39
+ {
40
+ path: '/docs',
41
+ description: 'Complete API documentation and integration guides'
42
+ },
43
+ {
44
+ path: '/docs/getting-started',
45
+ description: 'Quick start guide for new users'
46
+ },
47
+ {
48
+ path: '/api/reference',
49
+ description: 'REST API reference with all endpoints and schemas'
50
+ },
51
+ {
52
+ path: '/blog',
53
+ description: 'Technical blog posts and product updates'
54
+ },
55
+ {
56
+ path: '/pricing',
57
+ description: 'Pricing plans and feature comparison'
58
+ }
59
+ ],
60
+
61
+ // Optional: External resources
62
+ externalLinks: [
63
+ {
64
+ title: 'GitHub Repository',
65
+ url: 'https://github.com/example/project',
66
+ description: 'Open-source code and issue tracker'
67
+ },
68
+ {
69
+ title: 'API Status',
70
+ url: 'https://status.example.com',
71
+ description: 'Real-time API status and incident reports'
72
+ }
73
+ ],
74
+
75
+ // Optional: Organization info for JSON-LD schemas (used on 'about' pages)
76
+ organization: {
77
+ name: 'Example Corp',
78
+ description: 'Building the future of AI-optimized web applications',
79
+ url: 'https://example.com',
80
+ logo: 'https://example.com/logo.png',
81
+ foundingDate: '2024-01-01'
82
+ },
83
+
84
+ // Optional: Custom sections with any markdown content
85
+ sections: [
86
+ {
87
+ heading: 'About',
88
+ content: `This project helps teams collaborate more effectively by providing
89
+ a unified workspace for tasks, projects, and documentation. It integrates with
90
+ popular tools like GitHub, Slack, and Jira.`
91
+ },
92
+ {
93
+ heading: 'Key Features',
94
+ content: `- **Task Management**: Create, assign, and track tasks across teams
95
+ - **Real-time Collaboration**: WebSocket-based updates for instant sync
96
+ - **Rich API**: RESTful API with comprehensive documentation
97
+ - **Integrations**: Connect with 50+ external services
98
+ - **Security**: SOC 2 Type II certified with end-to-end encryption`
99
+ },
100
+ {
101
+ heading: 'Use Cases',
102
+ content: `**For Development Teams**: Track sprints, manage backlogs, and integrate with CI/CD pipelines.
103
+
104
+ **For Content Teams**: Plan editorial calendars, collaborate on drafts, and publish content.
105
+
106
+ **For Product Teams**: Gather feedback, prioritize features, and communicate roadmaps.`
107
+ }
108
+ ]
109
+ };
110
+
111
+ export default config;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ontosdk/next",
3
- "version": "1.1.0",
3
+ "version": "1.3.0",
4
4
  "description": "Extracts semantic Markdown from React/Next.js pages for AI Agents",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -18,6 +18,21 @@
18
18
  "require": "./dist/middleware.js",
19
19
  "import": "./dist/middleware.mjs",
20
20
  "types": "./dist/middleware.d.ts"
21
+ },
22
+ "./components": {
23
+ "require": "./dist/OntoHead.js",
24
+ "import": "./dist/OntoHead.mjs",
25
+ "types": "./dist/OntoHead.d.ts"
26
+ },
27
+ "./provider": {
28
+ "require": "./dist/OntoProvider.js",
29
+ "import": "./dist/OntoProvider.mjs",
30
+ "types": "./dist/OntoProvider.d.ts"
31
+ },
32
+ "./config": {
33
+ "require": "./dist/config.js",
34
+ "import": "./dist/config.mjs",
35
+ "types": "./dist/config.d.ts"
21
36
  }
22
37
  },
23
38
  "bin": {
@@ -43,11 +58,22 @@
43
58
  "picocolors": "^1.0.0",
44
59
  "turndown": "^7.1.3"
45
60
  },
61
+ "peerDependencies": {
62
+ "next": ">=14.0.0",
63
+ "react": "^18.0.0 || ^19.0.0"
64
+ },
65
+ "peerDependenciesMeta": {
66
+ "react": {
67
+ "optional": true
68
+ }
69
+ },
46
70
  "devDependencies": {
47
71
  "@types/node": "^20.11.24",
72
+ "@types/react": "^19.2.14",
48
73
  "@types/turndown": "^5.0.4",
49
74
  "next": "^16.1.6",
75
+ "react": "^19.2.4",
50
76
  "tsup": "^8.0.2",
51
77
  "typescript": "^5.3.3"
52
78
  }
53
- }
79
+ }
@@ -0,0 +1,59 @@
1
+ 'use client';
2
+
3
+ import { usePathname } from 'next/navigation';
4
+
5
+ /**
6
+ * OntoHead — Auto-Discovery component for AI agents.
7
+ *
8
+ * Injects `<link rel="alternate">` tags into the page `<head>` so AI crawlers
9
+ * can discover the optimized markdown endpoint for the current route.
10
+ *
11
+ * Usage in a Next.js App Router layout:
12
+ * ```tsx
13
+ * import { OntoHead } from '@ontosdk/next/components';
14
+ *
15
+ * export default function RootLayout({ children }) {
16
+ * return (
17
+ * <html>
18
+ * <head>
19
+ * <OntoHead />
20
+ * </head>
21
+ * <body>{children}</body>
22
+ * </html>
23
+ * );
24
+ * }
25
+ * ```
26
+ */
27
+ export function OntoHead() {
28
+ const pathname = usePathname();
29
+
30
+ // Map current route to its .onto markdown payload path
31
+ let payloadPath = pathname;
32
+ if (payloadPath === '/' || payloadPath === '') {
33
+ payloadPath = '/index';
34
+ }
35
+ if (payloadPath.endsWith('/') && payloadPath !== '/') {
36
+ payloadPath = payloadPath.slice(0, -1);
37
+ }
38
+
39
+ const markdownHref = `/.onto${payloadPath}.md`;
40
+
41
+ return (
42
+ <>
43
+ {/* Per-page markdown alternate for AI agents */}
44
+ <link
45
+ rel="alternate"
46
+ type="text/markdown"
47
+ href={markdownHref}
48
+ title="AI-optimized Markdown version"
49
+ />
50
+ {/* Site-wide llms.txt manifest */}
51
+ <link
52
+ rel="alternate"
53
+ type="text/plain"
54
+ href="/llms.txt"
55
+ title="LLM-readable site manifest"
56
+ />
57
+ </>
58
+ );
59
+ }
@@ -0,0 +1,95 @@
1
+ 'use client';
2
+
3
+ import { usePathname } from 'next/navigation';
4
+ import { ReactNode, useMemo } from 'react';
5
+ import type { OntoConfig, PageType } from './config';
6
+ import { generateSchemaForPageType, serializeSchema } from './schemas';
7
+
8
+ export interface OntoProviderProps {
9
+ /**
10
+ * The base URL of your site (e.g., 'https://example.com')
11
+ * Used to construct the full href for the AI discovery link tag.
12
+ */
13
+ baseUrl: string;
14
+ /**
15
+ * Child components to render
16
+ */
17
+ children: ReactNode;
18
+ /**
19
+ * Optional: Onto configuration for automatic JSON-LD schema injection
20
+ * If provided, the provider will automatically inject JSON-LD schemas
21
+ * based on the page type configuration
22
+ */
23
+ config?: OntoConfig;
24
+ }
25
+
26
+ /**
27
+ * OntoProvider — Automatic AI Discovery Provider
28
+ *
29
+ * Wraps your application and automatically injects:
30
+ * 1. `<link rel="alternate">` tags for AI discovery
31
+ * 2. JSON-LD structured data schemas based on page type
32
+ *
33
+ * With config, automatically generates JSON-LD schemas:
34
+ * - 'scoring' pages get Methodology schema with AIO weights (40/35/25)
35
+ * - 'about' pages get Organization/AboutPage schema
36
+ *
37
+ * Usage in a Next.js App Router layout:
38
+ * ```tsx
39
+ * import { OntoProvider } from '@ontosdk/next/provider';
40
+ * import config from '../onto.config';
41
+ *
42
+ * export default function RootLayout({ children }) {
43
+ * return (
44
+ * <OntoProvider baseUrl="https://example.com" config={config}>
45
+ * <html>
46
+ * <head />
47
+ * <body>{children}</body>
48
+ * </html>
49
+ * </OntoProvider>
50
+ * );
51
+ * }
52
+ * ```
53
+ */
54
+ export function OntoProvider({ baseUrl, children, config }: OntoProviderProps) {
55
+ const pathname = usePathname();
56
+
57
+ // Construct the full URL with the current path and ?format=md query string
58
+ const cleanBaseUrl = baseUrl.endsWith('/') ? baseUrl.slice(0, -1) : baseUrl;
59
+ const markdownHref = `${cleanBaseUrl}${pathname}?format=md`;
60
+ const fullPageUrl = `${cleanBaseUrl}${pathname}`;
61
+
62
+ // Determine page type from config routes
63
+ const pageType: PageType = useMemo(() => {
64
+ if (!config?.routes) return 'default';
65
+
66
+ const matchingRoute = config.routes.find(route => route.path === pathname);
67
+ return matchingRoute?.pageType || 'default';
68
+ }, [config, pathname]);
69
+
70
+ // Generate JSON-LD schema based on page type
71
+ const jsonLdSchema = useMemo(() => {
72
+ if (!config || pageType === 'default') return null;
73
+
74
+ const schema = generateSchemaForPageType(pageType, config, fullPageUrl);
75
+ return serializeSchema(schema);
76
+ }, [config, pageType, fullPageUrl]);
77
+
78
+ return (
79
+ <>
80
+ <link
81
+ rel="alternate"
82
+ type="text/markdown"
83
+ href={markdownHref}
84
+ title="AI-optimized Markdown version"
85
+ />
86
+ {jsonLdSchema && (
87
+ <script
88
+ type="application/ld+json"
89
+ dangerouslySetInnerHTML={{ __html: jsonLdSchema }}
90
+ />
91
+ )}
92
+ {children}
93
+ </>
94
+ );
95
+ }
package/src/bots.ts ADDED
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Comprehensive registry of AI bot user-agent strings.
3
+ * The middleware uses this list to detect AI crawlers and serve optimized markdown.
4
+ */
5
+
6
+ export interface AiBot {
7
+ /** The user-agent substring to match against */
8
+ name: string;
9
+ /** The company operating this bot */
10
+ company: string;
11
+ }
12
+
13
+ /**
14
+ * Structured registry of all known AI bots, grouped by company.
15
+ * Useful for analytics and the Control Plane dashboard.
16
+ */
17
+ export const AI_BOTS: AiBot[] = [
18
+ // OpenAI
19
+ { name: 'GPTBot', company: 'OpenAI' },
20
+ { name: 'ChatGPT-User', company: 'OpenAI' },
21
+ { name: 'OAI-SearchBot', company: 'OpenAI' },
22
+
23
+ // Google
24
+ { name: 'Googlebot', company: 'Google' },
25
+ { name: 'Google-CloudVertexBot', company: 'Google' },
26
+ { name: 'Google-Extended', company: 'Google' },
27
+ { name: 'GoogleOther', company: 'Google' },
28
+
29
+ // Anthropic
30
+ { name: 'ClaudeBot', company: 'Anthropic' },
31
+ { name: 'Claude-User', company: 'Anthropic' },
32
+ { name: 'anthropic-ai', company: 'Anthropic' },
33
+
34
+ // Perplexity
35
+ { name: 'PerplexityBot', company: 'Perplexity' },
36
+ { name: 'Perplexity-User', company: 'Perplexity' },
37
+
38
+ // Meta
39
+ { name: 'Meta-ExternalAgent', company: 'Meta' },
40
+ { name: 'Meta-ExternalFetcher', company: 'Meta' },
41
+ { name: 'FacebookBot', company: 'Meta' },
42
+
43
+ // Common Crawl (used by most smaller AI companies)
44
+ { name: 'CCBot', company: 'Common Crawl' },
45
+
46
+ // Other notable AI crawlers
47
+ { name: 'Bytespider', company: 'ByteDance' },
48
+ { name: 'Applebot-Extended', company: 'Apple' },
49
+ { name: 'cohere-ai', company: 'Cohere' },
50
+ { name: 'YouBot', company: 'You.com' },
51
+ ];
52
+
53
+ /**
54
+ * Flat list of user-agent substrings for fast matching in the middleware.
55
+ */
56
+ export const AI_BOT_USER_AGENTS: string[] = AI_BOTS.map(bot => bot.name);
57
+
58
+ /**
59
+ * Given a raw user-agent string, returns the matched AiBot entry or undefined.
60
+ * Comparison is case-insensitive to handle inconsistent agent casing.
61
+ */
62
+ export function matchBot(userAgent: string | null): AiBot | undefined {
63
+ if (!userAgent) return undefined;
64
+ const lowerUA = userAgent.toLowerCase();
65
+ return AI_BOTS.find(bot =>
66
+ lowerUA.includes(bot.name.toLowerCase())
67
+ );
68
+ }
package/src/cli.ts CHANGED
@@ -5,7 +5,24 @@ import path from 'path';
5
5
  import pc from 'picocolors';
6
6
  import { extractContent } from './extractor';
7
7
 
8
+ // Simple helper to load .env.local from the current working directory
9
+ function loadEnv() {
10
+ const envPath = path.join(process.cwd(), '.env.local');
11
+ if (fs.existsSync(envPath)) {
12
+ const envContent = fs.readFileSync(envPath, 'utf8');
13
+ envContent.split(/\r?\n/).forEach(line => {
14
+ const trimmedLine = line.trim();
15
+ if (!trimmedLine || trimmedLine.startsWith('#')) return;
16
+ const [key, ...valueParts] = trimmedLine.split('=');
17
+ if (key && valueParts.length > 0) {
18
+ process.env[key.trim()] = valueParts.join('=').trim().replace(/^["']|["']$/g, '');
19
+ }
20
+ });
21
+ }
22
+ }
23
+
8
24
  async function main() {
25
+ loadEnv();
9
26
  console.log(pc.cyan('\n[Onto] Starting Semantic Output Generation...'));
10
27
 
11
28
  const cwd = process.cwd();
@@ -89,7 +106,7 @@ async function main() {
89
106
  const DASHBOARD_URL = process.env.ONTO_DASHBOARD_URL || 'https://app.buildonto.dev';
90
107
 
91
108
  if (ONTO_API_KEY && totalFilesProcessed > 0) {
92
- console.log(pc.cyan('[Onto] Syncing manifest with Control Plane...'));
109
+ console.log(pc.cyan(`[Onto] Syncing manifest with Control Plane [${DASHBOARD_URL}]...`));
93
110
  try {
94
111
  const manifest = files.map(file => {
95
112
  const routeName = file.replace(/\.html$/, '');