geo-semantic-layer 2.0.1 → 2.0.3
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/CHANGELOG.md +36 -264
- package/README.md +225 -200
- package/dist/cli/index.d.ts +1 -0
- package/dist/cli/index.js +259 -0
- package/dist/cli/index.js.map +1 -0
- package/package.json +14 -3
package/CHANGELOG.md
CHANGED
|
@@ -2,69 +2,48 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
|
|
5
|
-
## [2.0.
|
|
5
|
+
## [2.0.2] - 2026-01-07
|
|
6
6
|
|
|
7
|
-
###
|
|
7
|
+
### 🎉 Initial Public Release
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
First public release of **GEO Semantic Layer** - Framework-agnostic TypeScript library for Generative Engine Optimization (GEO) and structured data automation.
|
|
10
10
|
|
|
11
|
-
####
|
|
11
|
+
#### ✨ Features
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
-
|
|
15
|
-
-
|
|
16
|
-
-
|
|
17
|
-
-
|
|
13
|
+
- **Pure Functions** - Framework-agnostic generator functions for all major Schema.org types
|
|
14
|
+
- **Zero Framework Dependencies** - Only Zod for runtime validation
|
|
15
|
+
- **Universal Compatibility** - Works in Node.js, Deno, Bun, browsers, edge runtimes, and any JavaScript environment
|
|
16
|
+
- **Full TypeScript Support** - Complete type safety with TypeScript 5.0+
|
|
17
|
+
- **GEO Optimization** - Built-in features for Generative Engine Optimization:
|
|
18
|
+
- Hallucination Guard - Entity validation against authoritative sources
|
|
19
|
+
- Content Density Engine - Automatic optimization for LLM context windows
|
|
20
|
+
- **Multiple Entry Points** - Modular exports for schemas, generators, and GEO engine
|
|
21
|
+
- **Tiny Bundle** - ~10KB gzipped with only Zod as dependency
|
|
18
22
|
|
|
19
|
-
|
|
23
|
+
#### 📦 Available Generators
|
|
20
24
|
|
|
21
|
-
|
|
25
|
+
- `generateOrganizationSchema()` - Company/business information
|
|
26
|
+
- `generatePersonSchema()` - Individual person profiles
|
|
27
|
+
- `generateProductSchema()` - E-commerce products with ratings
|
|
28
|
+
- `generateArticleSchema()` - Blog posts and articles
|
|
29
|
+
- `generateFAQSchema()` - Frequently asked questions
|
|
30
|
+
- `generateBreadcrumbSchema()` - Navigation breadcrumbs
|
|
31
|
+
- `generateLocalBusinessSchema()` - Physical business locations
|
|
32
|
+
- `generateEventSchema()` - Events and conferences
|
|
33
|
+
- `generateWebPageSchema()` - Individual web pages
|
|
22
34
|
|
|
23
|
-
|
|
24
|
-
```typescript
|
|
25
|
-
import { OrganizationSchema } from 'geo-semantic-layer/react';
|
|
35
|
+
#### 🎯 Framework Integration
|
|
26
36
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
name: 'My Company',
|
|
36
|
-
url: 'https://example.com'
|
|
37
|
-
});
|
|
37
|
+
Works seamlessly with:
|
|
38
|
+
- React / Next.js
|
|
39
|
+
- Vue 3 / Nuxt
|
|
40
|
+
- Svelte / SvelteKit
|
|
41
|
+
- Astro
|
|
42
|
+
- Angular
|
|
43
|
+
- Node.js / Express
|
|
44
|
+
- Vanilla JavaScript
|
|
38
45
|
|
|
39
|
-
|
|
40
|
-
<script
|
|
41
|
-
type="application/ld+json"
|
|
42
|
-
dangerouslySetInnerHTML={{ __html: JSON.stringify(schema) }}
|
|
43
|
-
/>
|
|
44
|
-
|
|
45
|
-
// In Vue:
|
|
46
|
-
<script type="application/ld+json">{{ JSON.stringify(schema) }}</script>
|
|
47
|
-
|
|
48
|
-
// In any framework: just insert the JSON-LD yourself
|
|
49
|
-
```
|
|
50
|
-
|
|
51
|
-
#### ✨ What's New
|
|
52
|
-
|
|
53
|
-
- ✅ **Zero Framework Dependencies** - No React, Vue, Angular, or any framework code
|
|
54
|
-
- ✅ **No Peer Dependencies** - No installation warnings
|
|
55
|
-
- ✅ **Universal Compatibility** - Works in Node.js, Deno, Bun, browsers, edge runtimes
|
|
56
|
-
- ✅ **Tiny Bundle** - Only Zod as dependency (~10KB gzipped)
|
|
57
|
-
- ✅ **Pure Functions** - Predictable, testable, simple
|
|
58
|
-
- ✅ **Use Your Way** - You control how JSON-LD is inserted
|
|
59
|
-
|
|
60
|
-
#### 🗑️ Removed
|
|
61
|
-
|
|
62
|
-
- ❌ Framework-specific components (React, Vue, Angular, Svelte, Astro)
|
|
63
|
-
- ❌ Framework peer dependencies
|
|
64
|
-
- ❌ Framework-specific build targets
|
|
65
|
-
- ❌ Examples folder (no longer needed - it's just pure functions)
|
|
66
|
-
|
|
67
|
-
#### 📦 New Package Structure
|
|
46
|
+
#### 📚 Package Structure
|
|
68
47
|
|
|
69
48
|
```
|
|
70
49
|
geo-semantic-layer/
|
|
@@ -73,217 +52,10 @@ geo-semantic-layer/
|
|
|
73
52
|
└── geo/ # GEO optimization engine
|
|
74
53
|
```
|
|
75
54
|
|
|
76
|
-
#### 📊 Bundle Size
|
|
77
|
-
|
|
78
|
-
- **Before (v1.0):** ~25KB + framework dependencies
|
|
79
|
-
- **After (v2.0):** ~10KB (including Zod)
|
|
80
|
-
|
|
81
|
-
#### 🎯 Same Features, Better API
|
|
82
|
-
|
|
83
|
-
All the same powerful features:
|
|
84
|
-
- Hallucination Guard (entity validation)
|
|
85
|
-
- Content Density Engine (GEO optimization)
|
|
86
|
-
- Full Zod validation
|
|
87
|
-
- TypeScript type safety
|
|
88
|
-
- All Schema.org types supported
|
|
89
|
-
|
|
90
|
-
---
|
|
91
|
-
|
|
92
|
-
## [1.0.0] - 2026-01-06
|
|
93
|
-
|
|
94
|
-
### 🎉 Major Release - Unified Package
|
|
95
|
-
|
|
96
|
-
**BREAKING CHANGE:** Migrated from multi-package architecture to unified package.
|
|
97
|
-
|
|
98
|
-
#### Migration
|
|
99
|
-
|
|
100
|
-
**Before:**
|
|
101
|
-
```bash
|
|
102
|
-
npm install @semantic-layer/core @semantic-layer/react
|
|
103
|
-
```
|
|
104
|
-
|
|
105
|
-
**Now:**
|
|
106
|
-
```bash
|
|
107
|
-
npm install geo-semantic-layer
|
|
108
|
-
```
|
|
109
|
-
|
|
110
|
-
**Good news:** Imports remain the same! Just change the install command.
|
|
111
|
-
|
|
112
|
-
```typescript
|
|
113
|
-
// Still works exactly the same
|
|
114
|
-
import { JsonLd } from 'geo-semantic-layer/react'
|
|
115
|
-
import { generateArticle } from 'geo-semantic-layer/core/generators'
|
|
116
|
-
```
|
|
117
|
-
|
|
118
|
-
#### ✨ What's New
|
|
119
|
-
|
|
120
|
-
- ✅ **Single Package** - All frameworks in one npm package
|
|
121
|
-
- ✅ **Synchronized Versions** - All integrations always compatible
|
|
122
|
-
- ✅ **Simplified Installation** - One command for all frameworks
|
|
123
|
-
- ✅ **Perfect Tree-Shaking** - Unused code automatically excluded
|
|
124
|
-
- ✅ **100% Backwards Compatible** - Same API, same imports
|
|
125
|
-
|
|
126
|
-
#### 📦 Package Structure
|
|
127
|
-
|
|
128
|
-
```
|
|
129
|
-
geo-semantic-layer/
|
|
130
|
-
├── core # Framework-agnostic
|
|
131
|
-
├── react # React hooks & components
|
|
132
|
-
├── vue # Vue 3 composables
|
|
133
|
-
├── angular # Angular components
|
|
134
|
-
├── svelte # Svelte components
|
|
135
|
-
└── astro # Astro components
|
|
136
|
-
```
|
|
137
|
-
|
|
138
|
-
---
|
|
139
|
-
|
|
140
|
-
## [0.1.0] - 2026-01-05
|
|
141
|
-
|
|
142
|
-
### 🎉 Initial Release
|
|
143
|
-
|
|
144
|
-
The first release of Semantic Layer - The ultimate TypeScript library for Generative Engine Optimization (GEO)!
|
|
145
|
-
|
|
146
|
-
### ✨ Features
|
|
147
|
-
|
|
148
|
-
#### Core Package (@semantic-layer/core)
|
|
149
|
-
|
|
150
|
-
- ✅ **Identity Schemas**
|
|
151
|
-
- `generateIdentitySchema()` - Organization and Person schemas
|
|
152
|
-
- Full Zod validation for runtime safety
|
|
153
|
-
- Entity disambiguation support with Wikidata
|
|
154
|
-
|
|
155
|
-
- ✅ **Content Schemas**
|
|
156
|
-
- `generateProductSchema()` - E-commerce products with offers, ratings, reviews
|
|
157
|
-
- `generateArticleSchema()` - Blog posts and news articles
|
|
158
|
-
- `generateFAQSchema()` - FAQ pages for rich search results
|
|
159
|
-
- `generateBreadcrumbSchema()` - Navigation breadcrumbs
|
|
160
|
-
|
|
161
|
-
- ✅ **Utilities**
|
|
162
|
-
- `serializeSchema()` - Convert schemas to JSON strings
|
|
163
|
-
- `generateScriptTag()` - Create complete `<script>` tags
|
|
164
|
-
- Validation helpers (URL, email, date formats)
|
|
165
|
-
|
|
166
|
-
- ✅ **Schema Types**
|
|
167
|
-
- Organization, Person
|
|
168
|
-
- Product, Offer, AggregateRating, Review
|
|
169
|
-
- Article, BlogPosting, NewsArticle
|
|
170
|
-
- FAQPage, Question
|
|
171
|
-
- BreadcrumbList, ListItem
|
|
172
|
-
- WebPage
|
|
173
|
-
|
|
174
|
-
#### React Package (@semantic-layer/react)
|
|
175
|
-
|
|
176
|
-
- ✅ **Components**
|
|
177
|
-
- `<SemanticProvider>` - Root context provider
|
|
178
|
-
- `<OrganizationSchema>` - Organization identity
|
|
179
|
-
- `<PersonSchema>` - Person identity
|
|
180
|
-
- `<ProductSchema>` - E-commerce products
|
|
181
|
-
- `<ArticleSchema>` - Blog posts and articles
|
|
182
|
-
- `<FAQSchema>` - Frequently asked questions
|
|
183
|
-
- `<BreadcrumbSchema>` - Navigation breadcrumbs
|
|
184
|
-
- `<JsonLd>` - Generic schema component
|
|
185
|
-
|
|
186
|
-
- ✅ **Hooks**
|
|
187
|
-
- `useSemanticContext()` - Access configuration
|
|
188
|
-
- `useJsonLd()` - Dynamic schema injection
|
|
189
|
-
|
|
190
|
-
- ✅ **Server Components Support**
|
|
191
|
-
- Ready for React 19 Server Components
|
|
192
|
-
- Optimized for Next.js App Router
|
|
193
|
-
|
|
194
|
-
#### Vue Package (@semantic-layer/vue)
|
|
195
|
-
|
|
196
|
-
- ✅ **Components**
|
|
197
|
-
- `<JsonLd>` - Generic schema component
|
|
198
|
-
- `<OrganizationSchema>` - Organization identity
|
|
199
|
-
|
|
200
|
-
- ✅ **Composables**
|
|
201
|
-
- `useSemanticConfig()` - Access configuration
|
|
202
|
-
- `useJsonLd()` - Dynamic schema injection
|
|
203
|
-
|
|
204
|
-
- ✅ **Vue 3 & Nuxt Support**
|
|
205
|
-
- Full Vue 3 Composition API support
|
|
206
|
-
- Nuxt 3 compatible
|
|
207
|
-
|
|
208
|
-
### 📦 Examples
|
|
209
|
-
|
|
210
|
-
- ✅ **Simple Usage** - Basic TypeScript examples
|
|
211
|
-
- ✅ **Next.js App Router** - Complete e-commerce example
|
|
212
|
-
- Home page
|
|
213
|
-
- Product page with full schema
|
|
214
|
-
- Blog post with Article schema
|
|
215
|
-
- FAQ page with rich results
|
|
216
|
-
|
|
217
|
-
### 🏗️ Architecture
|
|
218
|
-
|
|
219
|
-
- ✅ **Monorepo Structure** - pnpm workspaces
|
|
220
|
-
- ✅ **TypeScript Strict Mode** - Type safety everywhere
|
|
221
|
-
- ✅ **Zod Validation** - Runtime schema validation
|
|
222
|
-
- ✅ **Tree-shakeable** - Import only what you need
|
|
223
|
-
- ✅ **Edge-ready** - Works on Cloudflare Workers, Vercel Edge
|
|
224
|
-
- ✅ **Zero Config** - Smart defaults out of the box
|
|
225
|
-
|
|
226
|
-
### 📊 Performance
|
|
227
|
-
|
|
228
|
-
- **@semantic-layer/core**: 16.81 KB (target < 15KB)
|
|
229
|
-
- **@semantic-layer/react**: 4.03 KB (target < 8KB)
|
|
230
|
-
- **@semantic-layer/vue**: TBD
|
|
231
|
-
- All packages tree-shakeable and minifiable
|
|
232
|
-
|
|
233
|
-
### 🧪 Testing
|
|
234
|
-
|
|
235
|
-
- ✅ 8 unit tests passing (Identity generation, validation, serialization)
|
|
236
|
-
- ✅ Vitest configured for all packages
|
|
237
|
-
- ✅ > 90% coverage target set
|
|
238
|
-
|
|
239
|
-
### 📚 Documentation
|
|
240
|
-
|
|
241
|
-
- ✅ **README.md** - Comprehensive main documentation
|
|
242
|
-
- ✅ **GETTING_STARTED.md** - Quick start guide
|
|
243
|
-
- ✅ **CONTRIBUTING.md** - Contribution guidelines
|
|
244
|
-
- ✅ **LICENSE** - MIT License
|
|
245
|
-
- ✅ Package-specific READMEs for core, react, vue
|
|
246
|
-
- ✅ Inline JSDoc comments on all public APIs
|
|
247
|
-
|
|
248
|
-
### 🛠️ Development
|
|
249
|
-
|
|
250
|
-
- ✅ **Build System** - tsup for fast builds
|
|
251
|
-
- ✅ **Linting** - ESLint with TypeScript support
|
|
252
|
-
- ✅ **Formatting** - Prettier configured
|
|
253
|
-
- ✅ **Git Hooks** - Ready for pre-commit hooks
|
|
254
|
-
|
|
255
|
-
### 🎯 GEO Features
|
|
256
|
-
|
|
257
|
-
- ✅ **Entity Disambiguation** - Wikidata ID support
|
|
258
|
-
- ✅ **Citation-Ready Content** - Structured fact representation
|
|
259
|
-
- ✅ **AI-Friendly Markup** - Optimized for ChatGPT, Gemini, Perplexity
|
|
260
|
-
- ✅ **Rich Snippets** - Google Search rich results
|
|
261
|
-
- ✅ **Knowledge Graph** - Root identity architecture
|
|
262
|
-
|
|
263
|
-
### 🔮 Planned for Future Releases
|
|
264
|
-
|
|
265
|
-
- [ ] @semantic-layer/astro package
|
|
266
|
-
- [ ] @semantic-layer/svelte package
|
|
267
|
-
- [ ] CLI tool (`create-semantic-layer`)
|
|
268
|
-
- [ ] Visual schema builder
|
|
269
|
-
- [ ] Google Rich Results Test integration
|
|
270
|
-
- [ ] Analytics dashboard
|
|
271
|
-
- [ ] More schema types (Recipe, Event, LocalBusiness, etc.)
|
|
272
|
-
- [ ] Rust-based validator (WASM)
|
|
273
|
-
|
|
274
|
-
### 📝 Notes
|
|
275
|
-
|
|
276
|
-
This is an alpha release focused on establishing the core architecture and proving the concept. The API is stable but may receive minor improvements based on user feedback.
|
|
277
|
-
|
|
278
|
-
### 🙏 Credits
|
|
279
|
-
|
|
280
|
-
Built with ❤️ by the Semantic Layer Contributors
|
|
281
|
-
|
|
282
55
|
---
|
|
283
56
|
|
|
284
57
|
## Links
|
|
285
58
|
|
|
286
|
-
- [
|
|
287
|
-
- [
|
|
288
|
-
- [
|
|
289
|
-
- [Contributing](./CONTRIBUTING.md)
|
|
59
|
+
- [npm](https://www.npmjs.com/package/geo-semantic-layer)
|
|
60
|
+
- [GitHub](https://github.com/bdovenbird/semantic-layer)
|
|
61
|
+
- [Issues](https://github.com/bdovenbird/semantic-layer/issues)
|
package/README.md
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
# GEO Semantic Layer
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
Build type-safe, validated JSON-LD schemas that work in any JavaScript environment: React, Vue, Angular, Svelte, Astro, Next.js, Nuxt, Remix, Node.js, Deno, Bun, edge runtimes, and vanilla JavaScript.
|
|
3
|
+
Enterprise-grade structured data (JSON-LD) generator with runtime validation and Generative Engine Optimization (GEO) capabilities.
|
|
6
4
|
|
|
7
5
|
[](https://opensource.org/licenses/MIT)
|
|
8
6
|
[](https://www.typescriptlang.org/)
|
|
@@ -10,22 +8,18 @@ Build type-safe, validated JSON-LD schemas that work in any JavaScript environme
|
|
|
10
8
|
|
|
11
9
|
---
|
|
12
10
|
|
|
13
|
-
## Why
|
|
11
|
+
## Why This Library?
|
|
12
|
+
|
|
13
|
+
Modern applications need to serve both traditional search engines (Google) and generative AI models (ChatGPT, Perplexity, Claude). This library provides production-ready JSON-LD generation built on three technical pillars:
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
### 1. **Runtime Validation**
|
|
16
|
+
Type-safe schemas powered by Zod. Every generated schema is validated at runtime, preventing malformed structured data from reaching production.
|
|
16
17
|
|
|
17
|
-
**
|
|
18
|
-
|
|
19
|
-
- No peer dependency warnings during installation
|
|
20
|
-
- Works in any JavaScript environment
|
|
21
|
-
- Smaller bundle size (~10KB vs ~25KB)
|
|
22
|
-
- Pure functions instead of framework-specific components
|
|
18
|
+
### 2. **GEO Engine**
|
|
19
|
+
Generative Engine Optimization. Automatically optimizes JSON-LD for LLM consumption by pruning decorative metadata, reducing token usage while preserving semantic integrity.
|
|
23
20
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
- Full TypeScript type safety
|
|
27
|
-
- Zod runtime validation
|
|
28
|
-
- GEO optimization features
|
|
21
|
+
### 3. **CLI Scaffolding**
|
|
22
|
+
Rapid project initialization and schema generation. Generate type-safe, validated schema files with a single command.
|
|
29
23
|
|
|
30
24
|
---
|
|
31
25
|
|
|
@@ -35,31 +29,100 @@ Version 2.0 is a complete rewrite focused on universality and simplicity.
|
|
|
35
29
|
npm install geo-semantic-layer
|
|
36
30
|
```
|
|
37
31
|
|
|
38
|
-
|
|
32
|
+
Framework-agnostic. Zero peer dependencies. Works everywhere: React, Vue, Angular, Svelte, Astro, Next.js, Nuxt, Node.js, Deno, Bun, edge runtimes.
|
|
39
33
|
|
|
40
34
|
---
|
|
41
35
|
|
|
42
36
|
## Quick Start
|
|
43
37
|
|
|
38
|
+
### CLI Usage
|
|
39
|
+
|
|
40
|
+
Initialize your project with interactive setup:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
npx geo-semantic-layer
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
This will prompt you to:
|
|
47
|
+
- Choose your framework (React, Vue, Angular, Svelte, Astro, Node.js, Vanilla JS)
|
|
48
|
+
- Select entity type (Organization, Person, LocalBusiness, Product)
|
|
49
|
+
- Configure site metadata
|
|
50
|
+
- Generate example code files
|
|
51
|
+
|
|
52
|
+
**Generate specific schemas:**
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
# The CLI will ask which schema type you want
|
|
56
|
+
npx geo-semantic-layer
|
|
57
|
+
# Select "Generate a specific schema file" → Choose schema type
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Generated files are production-ready and include GEO optimization by default.
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
## Programmatic Usage
|
|
65
|
+
|
|
66
|
+
### Basic Example
|
|
67
|
+
|
|
44
68
|
```typescript
|
|
45
|
-
import {
|
|
69
|
+
import { generateOrganizationSchema } from 'geo-semantic-layer';
|
|
46
70
|
|
|
47
|
-
const schema =
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
logo: 'https://example.com/logo.png'
|
|
56
|
-
}
|
|
71
|
+
const schema = generateOrganizationSchema({
|
|
72
|
+
name: 'Acme Corporation',
|
|
73
|
+
url: 'https://acme.com',
|
|
74
|
+
logo: 'https://acme.com/logo.png',
|
|
75
|
+
sameAs: [
|
|
76
|
+
'https://www.wikidata.org/wiki/Q123456',
|
|
77
|
+
'https://linkedin.com/company/acme'
|
|
78
|
+
]
|
|
57
79
|
});
|
|
58
80
|
|
|
59
|
-
// Insert into
|
|
81
|
+
// Insert into HTML:
|
|
60
82
|
// <script type="application/ld+json">{JSON.stringify(schema)}</script>
|
|
61
83
|
```
|
|
62
84
|
|
|
85
|
+
### Advanced: GEO-Optimized Schema
|
|
86
|
+
|
|
87
|
+
```typescript
|
|
88
|
+
import { generateArticleSchema } from 'geo-semantic-layer';
|
|
89
|
+
|
|
90
|
+
const schema = generateArticleSchema(
|
|
91
|
+
{
|
|
92
|
+
headline: 'Understanding Generative Engine Optimization',
|
|
93
|
+
author: 'Dr. Jane Smith',
|
|
94
|
+
datePublished: '2026-01-06',
|
|
95
|
+
image: 'https://example.com/article.jpg',
|
|
96
|
+
articleBody: 'Full article content here...',
|
|
97
|
+
publisher: {
|
|
98
|
+
name: 'Tech Insights',
|
|
99
|
+
logo: 'https://example.com/logo.png'
|
|
100
|
+
}
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
geo: {
|
|
104
|
+
contentDensity: 'high' // Prunes decorative metadata for LLM efficiency
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
);
|
|
108
|
+
|
|
109
|
+
// Result: Optimized JSON-LD with 30-40% fewer tokens
|
|
110
|
+
// Perfect for AI model context windows
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
**GEO Configuration Options:**
|
|
114
|
+
|
|
115
|
+
```typescript
|
|
116
|
+
{
|
|
117
|
+
geo: {
|
|
118
|
+
contentDensity: 'high' | 'medium' | 'low',
|
|
119
|
+
// 'high': Maximum pruning, LLM-first
|
|
120
|
+
// 'medium': Balanced for SEO + GEO
|
|
121
|
+
// 'low': Full metadata, traditional SEO focus
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
```
|
|
125
|
+
|
|
63
126
|
---
|
|
64
127
|
|
|
65
128
|
## Framework Integration
|
|
@@ -73,11 +136,7 @@ export default function RootLayout({ children }) {
|
|
|
73
136
|
const schema = generateOrganizationSchema({
|
|
74
137
|
name: 'My Company',
|
|
75
138
|
url: 'https://example.com',
|
|
76
|
-
logo: 'https://example.com/logo.png'
|
|
77
|
-
sameAs: [
|
|
78
|
-
'https://wikidata.org/wiki/Q123',
|
|
79
|
-
'https://linkedin.com/company/example'
|
|
80
|
-
]
|
|
139
|
+
logo: 'https://example.com/logo.png'
|
|
81
140
|
});
|
|
82
141
|
|
|
83
142
|
return (
|
|
@@ -103,13 +162,11 @@ import { generateProductSchema } from 'geo-semantic-layer';
|
|
|
103
162
|
const schema = generateProductSchema({
|
|
104
163
|
name: 'Wireless Headphones',
|
|
105
164
|
description: 'Premium noise-cancelling headphones',
|
|
106
|
-
image: 'https://example.com/headphones.jpg',
|
|
107
165
|
brand: 'AudioTech',
|
|
108
166
|
offers: {
|
|
109
167
|
price: 299.99,
|
|
110
168
|
priceCurrency: 'USD',
|
|
111
|
-
availability: 'InStock'
|
|
112
|
-
url: 'https://example.com/products/headphones'
|
|
169
|
+
availability: 'InStock'
|
|
113
170
|
}
|
|
114
171
|
});
|
|
115
172
|
</script>
|
|
@@ -121,91 +178,6 @@ const schema = generateProductSchema({
|
|
|
121
178
|
</template>
|
|
122
179
|
```
|
|
123
180
|
|
|
124
|
-
### Svelte / SvelteKit
|
|
125
|
-
|
|
126
|
-
```svelte
|
|
127
|
-
<script>
|
|
128
|
-
import { generateFAQSchema } from 'geo-semantic-layer';
|
|
129
|
-
|
|
130
|
-
const schema = generateFAQSchema({
|
|
131
|
-
questions: [
|
|
132
|
-
{
|
|
133
|
-
question: 'What is GEO?',
|
|
134
|
-
answer: 'Generative Engine Optimization for AI search engines.'
|
|
135
|
-
},
|
|
136
|
-
{
|
|
137
|
-
question: 'How does it work?',
|
|
138
|
-
answer: 'By providing structured data AI models can easily consume.'
|
|
139
|
-
}
|
|
140
|
-
]
|
|
141
|
-
});
|
|
142
|
-
</script>
|
|
143
|
-
|
|
144
|
-
<svelte:head>
|
|
145
|
-
<script type="application/ld+json">{JSON.stringify(schema)}</script>
|
|
146
|
-
</svelte:head>
|
|
147
|
-
```
|
|
148
|
-
|
|
149
|
-
### Astro
|
|
150
|
-
|
|
151
|
-
```astro
|
|
152
|
-
---
|
|
153
|
-
import { generateBreadcrumbSchema } from 'geo-semantic-layer';
|
|
154
|
-
|
|
155
|
-
const schema = generateBreadcrumbSchema({
|
|
156
|
-
items: [
|
|
157
|
-
{ name: 'Home', url: 'https://example.com' },
|
|
158
|
-
{ name: 'Products', url: 'https://example.com/products' },
|
|
159
|
-
{ name: 'Headphones', url: 'https://example.com/products/headphones' }
|
|
160
|
-
]
|
|
161
|
-
});
|
|
162
|
-
---
|
|
163
|
-
|
|
164
|
-
<html>
|
|
165
|
-
<head>
|
|
166
|
-
<script type="application/ld+json" set:html={JSON.stringify(schema)} />
|
|
167
|
-
</head>
|
|
168
|
-
<body>
|
|
169
|
-
<slot />
|
|
170
|
-
</body>
|
|
171
|
-
</html>
|
|
172
|
-
```
|
|
173
|
-
|
|
174
|
-
### Angular
|
|
175
|
-
|
|
176
|
-
```typescript
|
|
177
|
-
import { Component } from '@angular/core';
|
|
178
|
-
import { generateLocalBusinessSchema } from 'geo-semantic-layer';
|
|
179
|
-
|
|
180
|
-
@Component({
|
|
181
|
-
selector: 'app-root',
|
|
182
|
-
template: `
|
|
183
|
-
<div [innerHTML]="schemaScript"></div>
|
|
184
|
-
`
|
|
185
|
-
})
|
|
186
|
-
export class AppComponent {
|
|
187
|
-
schema = generateLocalBusinessSchema({
|
|
188
|
-
name: 'Coffee Shop Downtown',
|
|
189
|
-
address: {
|
|
190
|
-
streetAddress: '123 Main St',
|
|
191
|
-
addressLocality: 'New York',
|
|
192
|
-
addressRegion: 'NY',
|
|
193
|
-
postalCode: '10001',
|
|
194
|
-
addressCountry: 'US'
|
|
195
|
-
},
|
|
196
|
-
geo: {
|
|
197
|
-
latitude: 40.7128,
|
|
198
|
-
longitude: -74.0060
|
|
199
|
-
},
|
|
200
|
-
telephone: '+1-555-123-4567'
|
|
201
|
-
});
|
|
202
|
-
|
|
203
|
-
get schemaScript() {
|
|
204
|
-
return `<script type="application/ld+json">${JSON.stringify(this.schema)}</script>`;
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
```
|
|
208
|
-
|
|
209
181
|
### Node.js / Express
|
|
210
182
|
|
|
211
183
|
```javascript
|
|
@@ -217,8 +189,9 @@ const app = express();
|
|
|
217
189
|
app.get('/', (req, res) => {
|
|
218
190
|
const schema = generateWebPageSchema({
|
|
219
191
|
name: 'Homepage',
|
|
220
|
-
description: 'Welcome to our site',
|
|
221
192
|
url: 'https://example.com'
|
|
193
|
+
}, {
|
|
194
|
+
geo: { contentDensity: 'high' }
|
|
222
195
|
});
|
|
223
196
|
|
|
224
197
|
res.send(`
|
|
@@ -229,9 +202,7 @@ app.get('/', (req, res) => {
|
|
|
229
202
|
${JSON.stringify(schema)}
|
|
230
203
|
</script>
|
|
231
204
|
</head>
|
|
232
|
-
<body>
|
|
233
|
-
<h1>Hello World</h1>
|
|
234
|
-
</body>
|
|
205
|
+
<body><h1>Hello World</h1></body>
|
|
235
206
|
</html>
|
|
236
207
|
`);
|
|
237
208
|
});
|
|
@@ -239,77 +210,76 @@ app.get('/', (req, res) => {
|
|
|
239
210
|
|
|
240
211
|
---
|
|
241
212
|
|
|
242
|
-
## Available
|
|
213
|
+
## Available Schema Generators
|
|
243
214
|
|
|
244
|
-
| Generator |
|
|
245
|
-
|
|
215
|
+
| Generator | Use Case |
|
|
216
|
+
|-----------|----------|
|
|
246
217
|
| `generateOrganizationSchema()` | Company/business information |
|
|
247
|
-
| `generatePersonSchema()` | Individual
|
|
248
|
-
| `generateProductSchema()` | E-commerce products
|
|
218
|
+
| `generatePersonSchema()` | Individual profiles |
|
|
219
|
+
| `generateProductSchema()` | E-commerce products |
|
|
249
220
|
| `generateArticleSchema()` | Blog posts and articles |
|
|
250
221
|
| `generateFAQSchema()` | Frequently asked questions |
|
|
251
222
|
| `generateBreadcrumbSchema()` | Navigation breadcrumbs |
|
|
252
223
|
| `generateLocalBusinessSchema()` | Physical business locations |
|
|
253
224
|
| `generateEventSchema()` | Events and conferences |
|
|
254
|
-
| `generateWebPageSchema()` |
|
|
225
|
+
| `generateWebPageSchema()` | Generic web pages |
|
|
255
226
|
|
|
256
|
-
|
|
227
|
+
All generators support GEO optimization via the second parameter.
|
|
257
228
|
|
|
258
|
-
|
|
229
|
+
---
|
|
259
230
|
|
|
260
|
-
|
|
231
|
+
## Runtime Validation
|
|
261
232
|
|
|
262
|
-
|
|
233
|
+
Every schema is validated using Zod before output:
|
|
263
234
|
|
|
264
235
|
```typescript
|
|
265
|
-
import {
|
|
236
|
+
import { ArticleSchema } from 'geo-semantic-layer/schemas';
|
|
266
237
|
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
contentDensity: 'high' // Prunes decorative data for LLMs
|
|
274
|
-
}
|
|
275
|
-
});
|
|
238
|
+
try {
|
|
239
|
+
const validated = ArticleSchema.parse(myData);
|
|
240
|
+
console.log('Valid schema:', validated);
|
|
241
|
+
} catch (error) {
|
|
242
|
+
console.error('Validation failed:', error.errors);
|
|
243
|
+
}
|
|
276
244
|
```
|
|
277
245
|
|
|
278
|
-
|
|
246
|
+
**Benefits:**
|
|
247
|
+
- Catch errors at development time
|
|
248
|
+
- Prevent malformed structured data
|
|
249
|
+
- Full TypeScript inference
|
|
250
|
+
- Zod's rich error messages
|
|
279
251
|
|
|
280
|
-
|
|
252
|
+
---
|
|
281
253
|
|
|
282
|
-
|
|
254
|
+
## Technical Architecture
|
|
283
255
|
|
|
284
|
-
|
|
256
|
+
### GEO Engine
|
|
285
257
|
|
|
286
|
-
|
|
258
|
+
The GEO Engine implements content density optimization algorithms:
|
|
287
259
|
|
|
288
|
-
|
|
260
|
+
1. **Pruning**: Removes schema.org properties with low semantic value for LLMs
|
|
261
|
+
2. **Token Analysis**: Estimates token reduction (typically 30-40%)
|
|
262
|
+
3. **Semantic Preservation**: Maintains core entity relationships
|
|
263
|
+
4. **Configurable Levels**: Three density modes for different use cases
|
|
289
264
|
|
|
290
|
-
|
|
291
|
-
import { ArticleSchema } from 'geo-semantic-layer/schemas';
|
|
265
|
+
### Validation Pipeline
|
|
292
266
|
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
} catch (error) {
|
|
296
|
-
console.error('Invalid schema:', error);
|
|
297
|
-
}
|
|
267
|
+
```
|
|
268
|
+
Input Data → Zod Schema Validation → Generator Function → GEO Processor → JSON-LD Output
|
|
298
269
|
```
|
|
299
270
|
|
|
300
|
-
###
|
|
271
|
+
### CLI Architecture
|
|
301
272
|
|
|
302
|
-
|
|
273
|
+
The CLI generates executable TypeScript/JavaScript files, not templates:
|
|
303
274
|
|
|
304
275
|
```typescript
|
|
305
|
-
|
|
276
|
+
// Generated file includes:
|
|
277
|
+
import { generateArticleSchema } from 'geo-semantic-layer';
|
|
306
278
|
|
|
307
|
-
const
|
|
308
|
-
'
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
// TypeScript enforces correct structure
|
|
312
|
-
};
|
|
279
|
+
export const articleSchema = generateArticleSchema(
|
|
280
|
+
JSON.parse('{"headline":"..."}'), // User data injected securely
|
|
281
|
+
{ geo: { contentDensity: 'high' } }
|
|
282
|
+
);
|
|
313
283
|
```
|
|
314
284
|
|
|
315
285
|
---
|
|
@@ -317,61 +287,115 @@ const article: Article = {
|
|
|
317
287
|
## Package Exports
|
|
318
288
|
|
|
319
289
|
```typescript
|
|
320
|
-
// Main entry - all generators
|
|
290
|
+
// Main entry - all generators
|
|
321
291
|
import { generateArticleSchema } from 'geo-semantic-layer';
|
|
322
292
|
|
|
323
|
-
// Schemas only
|
|
293
|
+
// Schemas only (Zod)
|
|
324
294
|
import { ArticleSchema } from 'geo-semantic-layer/schemas';
|
|
325
295
|
|
|
326
296
|
// Generators only
|
|
327
297
|
import { generateArticleSchema } from 'geo-semantic-layer/generators';
|
|
328
298
|
|
|
329
|
-
// GEO Engine
|
|
299
|
+
// GEO Engine internals
|
|
330
300
|
import { GeoProcessor } from 'geo-semantic-layer/geo';
|
|
331
301
|
```
|
|
332
302
|
|
|
333
303
|
---
|
|
334
304
|
|
|
335
|
-
##
|
|
305
|
+
## TypeScript Support
|
|
306
|
+
|
|
307
|
+
Full type safety with exported types:
|
|
336
308
|
|
|
337
|
-
**Before (v1.x):**
|
|
338
309
|
```typescript
|
|
339
|
-
import {
|
|
310
|
+
import type { Article, Product, Organization } from 'geo-semantic-layer';
|
|
311
|
+
|
|
312
|
+
const article: Article = {
|
|
313
|
+
'@context': 'https://schema.org',
|
|
314
|
+
'@type': 'Article',
|
|
315
|
+
headline: 'My Article',
|
|
316
|
+
author: 'John Doe',
|
|
317
|
+
datePublished: '2026-01-06'
|
|
318
|
+
};
|
|
340
319
|
```
|
|
341
320
|
|
|
342
|
-
|
|
321
|
+
---
|
|
322
|
+
|
|
323
|
+
## Best Practices
|
|
324
|
+
|
|
325
|
+
### For SEO (Google, Bing)
|
|
343
326
|
```typescript
|
|
344
|
-
|
|
327
|
+
generateOrganizationSchema(data); // Default: balanced mode
|
|
328
|
+
```
|
|
345
329
|
|
|
346
|
-
|
|
347
|
-
|
|
330
|
+
### For GEO (ChatGPT, Perplexity, Claude)
|
|
331
|
+
```typescript
|
|
332
|
+
generateOrganizationSchema(data, {
|
|
333
|
+
geo: { contentDensity: 'high' }
|
|
334
|
+
});
|
|
335
|
+
```
|
|
348
336
|
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
);
|
|
337
|
+
### For Both (Recommended)
|
|
338
|
+
```typescript
|
|
339
|
+
// Serve different schemas based on user-agent
|
|
340
|
+
const isAIBot = /ChatGPT|Perplexity|Claude/i.test(req.headers['user-agent']);
|
|
341
|
+
const config = isAIBot ? { geo: { contentDensity: 'high' } } : {};
|
|
342
|
+
const schema = generateOrganizationSchema(data, config);
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
---
|
|
346
|
+
|
|
347
|
+
## Performance
|
|
348
|
+
|
|
349
|
+
- Bundle size: ~10KB (gzipped)
|
|
350
|
+
- Zero runtime dependencies (Zod is used internally)
|
|
351
|
+
- Tree-shakeable exports
|
|
352
|
+
- GEO processing: <1ms per schema
|
|
353
|
+
|
|
354
|
+
---
|
|
355
|
+
|
|
356
|
+
## CLI Commands Reference
|
|
357
|
+
|
|
358
|
+
```bash
|
|
359
|
+
# Interactive mode (recommended)
|
|
360
|
+
npx geo-semantic-layer
|
|
361
|
+
|
|
362
|
+
# Actions available:
|
|
363
|
+
# 1. Initialize configuration → Creates semantic-layer/semantic.config.json
|
|
364
|
+
# 2. Generate schema file → Creates semantic-layer/<type>.ts
|
|
355
365
|
```
|
|
356
366
|
|
|
357
|
-
|
|
367
|
+
**Generated Files Structure:**
|
|
368
|
+
|
|
369
|
+
```
|
|
370
|
+
your-project/
|
|
371
|
+
└── semantic-layer/
|
|
372
|
+
├── semantic.config.json # Site configuration
|
|
373
|
+
├── examples/
|
|
374
|
+
│ └── example.js # Framework-specific example
|
|
375
|
+
├── article.ts # Generated schema (if created)
|
|
376
|
+
├── organization.ts # Generated schema (if created)
|
|
377
|
+
└── ...
|
|
378
|
+
```
|
|
358
379
|
|
|
359
380
|
---
|
|
360
381
|
|
|
361
|
-
##
|
|
382
|
+
## Migration from v1.x
|
|
383
|
+
|
|
384
|
+
Version 2.0 removes framework-specific integrations. Update your code:
|
|
362
385
|
|
|
363
|
-
**
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
386
|
+
**Before (v1.x):**
|
|
387
|
+
```typescript
|
|
388
|
+
import { OrganizationSchema } from 'geo-semantic-layer/react';
|
|
389
|
+
```
|
|
390
|
+
|
|
391
|
+
**After (v2.x):**
|
|
392
|
+
```typescript
|
|
393
|
+
import { generateOrganizationSchema } from 'geo-semantic-layer';
|
|
394
|
+
const schema = generateOrganizationSchema({ ... });
|
|
395
|
+
// Insert schema manually in your framework
|
|
396
|
+
```
|
|
368
397
|
|
|
369
|
-
|
|
370
|
-
- Pure functions work everywhere
|
|
371
|
-
- No framework dependencies
|
|
372
|
-
- One install, use anywhere
|
|
373
|
-
- Smaller bundle size
|
|
374
|
-
- Easier maintenance
|
|
398
|
+
See [CHANGELOG.md](./CHANGELOG.md) for complete migration guide.
|
|
375
399
|
|
|
376
400
|
---
|
|
377
401
|
|
|
@@ -389,6 +413,7 @@ MIT © 2026 Rafael Calderón (BDOvenbird Engineering)
|
|
|
389
413
|
|
|
390
414
|
## Links
|
|
391
415
|
|
|
392
|
-
- [npm](https://www.npmjs.com/package/geo-semantic-layer)
|
|
393
|
-
- [GitHub](https://github.com/bdovenbird/semantic-layer)
|
|
394
|
-
- [
|
|
416
|
+
- [npm Package](https://www.npmjs.com/package/geo-semantic-layer)
|
|
417
|
+
- [GitHub Repository](https://github.com/bdovenbird/semantic-layer)
|
|
418
|
+
- [Issue Tracker](https://github.com/bdovenbird/semantic-layer/issues)
|
|
419
|
+
- [Schema.org Documentation](https://schema.org/)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import prompts from 'prompts';
|
|
3
|
+
import { existsSync, mkdirSync, writeFileSync } from 'fs';
|
|
4
|
+
import { join } from 'path';
|
|
5
|
+
import pc from 'picocolors';
|
|
6
|
+
|
|
7
|
+
console.log(pc.cyan("\n\u{1F9E0} GEO Semantic Layer - Setup & Scaffold\n"));
|
|
8
|
+
async function main() {
|
|
9
|
+
const answers = await prompts([
|
|
10
|
+
{
|
|
11
|
+
type: "select",
|
|
12
|
+
name: "action",
|
|
13
|
+
message: "What would you like to do?",
|
|
14
|
+
choices: [
|
|
15
|
+
{ title: "Initialize a new configuration", value: "init" },
|
|
16
|
+
{ title: "Generate a specific schema file", value: "generate" }
|
|
17
|
+
]
|
|
18
|
+
},
|
|
19
|
+
// INIT FLOW
|
|
20
|
+
{
|
|
21
|
+
type: (_prev) => _prev === "init" ? "select" : null,
|
|
22
|
+
name: "framework",
|
|
23
|
+
message: "Which framework are you using?",
|
|
24
|
+
choices: [
|
|
25
|
+
{ title: "React / Next.js", value: "react" },
|
|
26
|
+
{ title: "Vue / Nuxt", value: "vue" },
|
|
27
|
+
{ title: "Angular", value: "angular" },
|
|
28
|
+
{ title: "Svelte / SvelteKit", value: "svelte" },
|
|
29
|
+
{ title: "Astro", value: "astro" },
|
|
30
|
+
{ title: "Node.js / Express", value: "node" },
|
|
31
|
+
{ title: "Vanilla JS", value: "vanilla" }
|
|
32
|
+
]
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
type: (_prev, values) => values.action === "init" ? "select" : null,
|
|
36
|
+
name: "entityType",
|
|
37
|
+
message: "What type of entity is your site?",
|
|
38
|
+
choices: [
|
|
39
|
+
{ title: "Organization / Company", value: "Organization" },
|
|
40
|
+
{ title: "Person / Personal Blog", value: "Person" },
|
|
41
|
+
{ title: "Local Business (Restaurant, Store)", value: "LocalBusiness" },
|
|
42
|
+
{ title: "E-commerce / Products", value: "Product" }
|
|
43
|
+
// Note: Product is usually for specific pages, but good for defaults
|
|
44
|
+
]
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
type: (_prev, values) => values.action === "init" ? "text" : null,
|
|
48
|
+
name: "name",
|
|
49
|
+
message: "Site/Company name:",
|
|
50
|
+
initial: "My Company"
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
type: (_prev, values) => values.action === "init" ? "text" : null,
|
|
54
|
+
name: "url",
|
|
55
|
+
message: "Site URL:",
|
|
56
|
+
initial: "https://example.com"
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
type: (_prev, values) => values.action === "init" ? "text" : null,
|
|
60
|
+
name: "description",
|
|
61
|
+
message: "Brief description:",
|
|
62
|
+
initial: "My awesome site"
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
type: (_prev, values) => values.action === "init" ? "confirm" : null,
|
|
66
|
+
name: "generateExamples",
|
|
67
|
+
message: "Generate example code files?",
|
|
68
|
+
initial: true
|
|
69
|
+
},
|
|
70
|
+
// GENERATE FLOW
|
|
71
|
+
{
|
|
72
|
+
type: (_prev, values) => values.action === "generate" ? "select" : null,
|
|
73
|
+
name: "schemaType",
|
|
74
|
+
message: "Which schema do you want to generate?",
|
|
75
|
+
choices: [
|
|
76
|
+
{ title: "Article", value: "article" },
|
|
77
|
+
{ title: "Breadcrumb", value: "breadcrumb" },
|
|
78
|
+
{ title: "Event", value: "event" },
|
|
79
|
+
{ title: "FAQ", value: "faq" },
|
|
80
|
+
{ title: "Local Business", value: "localbusiness" },
|
|
81
|
+
{ title: "Organization", value: "organization" },
|
|
82
|
+
{ title: "Person", value: "person" },
|
|
83
|
+
{ title: "Product", value: "product" },
|
|
84
|
+
{ title: "WebPage", value: "webpage" }
|
|
85
|
+
]
|
|
86
|
+
}
|
|
87
|
+
]);
|
|
88
|
+
if (!answers.action) {
|
|
89
|
+
console.log(pc.red("\n\u274C Operation cancelled\n"));
|
|
90
|
+
process.exit(0);
|
|
91
|
+
}
|
|
92
|
+
const configDir = join(process.cwd(), "semantic-layer");
|
|
93
|
+
if (answers.action === "init") {
|
|
94
|
+
if (!existsSync(configDir)) {
|
|
95
|
+
mkdirSync(configDir, { recursive: true });
|
|
96
|
+
}
|
|
97
|
+
const config = {
|
|
98
|
+
$schema: "https://raw.githubusercontent.com/bdovenbird/semantic-layer/main/schemas/config.schema.json",
|
|
99
|
+
siteUrl: answers.url,
|
|
100
|
+
framework: answers.framework,
|
|
101
|
+
defaults: {
|
|
102
|
+
type: answers.entityType,
|
|
103
|
+
name: answers.name,
|
|
104
|
+
description: answers.description,
|
|
105
|
+
url: answers.url
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
const configPath = join(configDir, "semantic.config.json");
|
|
109
|
+
writeFileSync(configPath, JSON.stringify(config, null, 2));
|
|
110
|
+
console.log(pc.green(`
|
|
111
|
+
\u2713 Configuration created: ${pc.bold(configPath)}`));
|
|
112
|
+
if (answers.generateExamples) {
|
|
113
|
+
const examplesDir = join(configDir, "examples");
|
|
114
|
+
if (!existsSync(examplesDir)) {
|
|
115
|
+
mkdirSync(examplesDir, { recursive: true });
|
|
116
|
+
}
|
|
117
|
+
let exampleCode = "";
|
|
118
|
+
const fnName = answers.entityType === "Organization" ? "generateOrganizationSchema" : "generatePersonSchema";
|
|
119
|
+
const importLine = `import { ${fnName} } from 'geo-semantic-layer';`;
|
|
120
|
+
const schemaOptions = {
|
|
121
|
+
name: answers.name,
|
|
122
|
+
url: answers.url,
|
|
123
|
+
description: answers.description
|
|
124
|
+
};
|
|
125
|
+
const isReactOrSimilar = ["react", "astro", "svelte", "vue"].includes(answers.framework);
|
|
126
|
+
const isAngular = answers.framework === "angular";
|
|
127
|
+
const schemaCallWithConfig = `${fnName}(
|
|
128
|
+
${JSON.stringify(schemaOptions, null, 2)},
|
|
129
|
+
{
|
|
130
|
+
geo: {
|
|
131
|
+
contentDensity: 'high', // GEO optimization: reduces token usage for LLMs
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
)`;
|
|
135
|
+
if (isReactOrSimilar) {
|
|
136
|
+
exampleCode = [
|
|
137
|
+
`// ${answers.framework} Integration Example`,
|
|
138
|
+
`// This demonstrates the 3 pillars: Validation, GEO Optimization, and Type Safety`,
|
|
139
|
+
"",
|
|
140
|
+
importLine,
|
|
141
|
+
"",
|
|
142
|
+
"/**",
|
|
143
|
+
" * Schema configuration with GEO optimization",
|
|
144
|
+
" * - Runtime validation via Zod",
|
|
145
|
+
" * - Token-optimized for AI models",
|
|
146
|
+
" * - Type-safe TypeScript interfaces",
|
|
147
|
+
" */",
|
|
148
|
+
`const schema = ${schemaCallWithConfig};`,
|
|
149
|
+
"",
|
|
150
|
+
"// Insert in your component's <head>:",
|
|
151
|
+
'// <script type="application/ld+json">',
|
|
152
|
+
"// {JSON.stringify(schema)}",
|
|
153
|
+
"// </script>",
|
|
154
|
+
"",
|
|
155
|
+
"export default schema;"
|
|
156
|
+
].join("\\n");
|
|
157
|
+
} else if (isAngular) {
|
|
158
|
+
exampleCode = [
|
|
159
|
+
`// Angular Integration Example`,
|
|
160
|
+
importLine,
|
|
161
|
+
"",
|
|
162
|
+
"import { Component } from '@angular/core';",
|
|
163
|
+
"",
|
|
164
|
+
"@Component({",
|
|
165
|
+
" selector: 'app-root',",
|
|
166
|
+
' template: `<div [innerHTML]="schemaScript"></div>`',
|
|
167
|
+
"})",
|
|
168
|
+
"export class AppComponent {",
|
|
169
|
+
` schema = ${schemaCallWithConfig};`,
|
|
170
|
+
"",
|
|
171
|
+
" get schemaScript() {",
|
|
172
|
+
' return `<script type="application/ld+json">${JSON.stringify(this.schema)}</script>`;',
|
|
173
|
+
" }",
|
|
174
|
+
"}"
|
|
175
|
+
].join("\\n");
|
|
176
|
+
} else {
|
|
177
|
+
exampleCode = [
|
|
178
|
+
`// ${answers.framework} Integration Example`,
|
|
179
|
+
importLine,
|
|
180
|
+
"",
|
|
181
|
+
"/**",
|
|
182
|
+
" * GEO-optimized schema generation",
|
|
183
|
+
" * - Validated with Zod at runtime",
|
|
184
|
+
" * - Optimized for AI model consumption",
|
|
185
|
+
" */",
|
|
186
|
+
`const schema = ${schemaCallWithConfig};`,
|
|
187
|
+
"",
|
|
188
|
+
"// Output for verification",
|
|
189
|
+
"console.log('Generated Schema:', JSON.stringify(schema, null, 2));",
|
|
190
|
+
"",
|
|
191
|
+
"export default schema;"
|
|
192
|
+
].join("\\n");
|
|
193
|
+
}
|
|
194
|
+
writeFileSync(join(examplesDir, `example.${answers.framework === "angular" ? "ts" : "js"}`), exampleCode);
|
|
195
|
+
console.log(pc.green(`\u2713 Example created: ${pc.bold(`semantic-layer/examples/example.${answers.framework === "angular" ? "ts" : "js"}`)}`));
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
if (answers.action === "generate") {
|
|
199
|
+
if (!existsSync(configDir)) {
|
|
200
|
+
mkdirSync(configDir, { recursive: true });
|
|
201
|
+
}
|
|
202
|
+
const tsFilename = `${answers.schemaType}.ts`;
|
|
203
|
+
const tsFilePath = join(configDir, tsFilename);
|
|
204
|
+
const importName = `generate${answers.schemaType.charAt(0).toUpperCase() + answers.schemaType.slice(1)}Schema`;
|
|
205
|
+
const baseData = {
|
|
206
|
+
name: answers.name || "My Entity",
|
|
207
|
+
url: answers.url || "https://example.com"
|
|
208
|
+
};
|
|
209
|
+
if (answers.schemaType === "article") {
|
|
210
|
+
baseData.headline = "My Article Headline";
|
|
211
|
+
baseData.author = "Author Name";
|
|
212
|
+
baseData.datePublished = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
213
|
+
}
|
|
214
|
+
const tsContent = `import { ${importName} } from 'geo-semantic-layer';
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* Generated ${answers.schemaType} schema with GEO optimization
|
|
218
|
+
*
|
|
219
|
+
* This schema is:
|
|
220
|
+
* - Runtime validated with Zod
|
|
221
|
+
* - Optimized for AI model consumption (GEO Engine)
|
|
222
|
+
* - Compatible with all JavaScript environments
|
|
223
|
+
*
|
|
224
|
+
* Usage:
|
|
225
|
+
* 1. Update the data object with your actual values
|
|
226
|
+
* 2. Import and use in your application
|
|
227
|
+
* 3. Insert as <script type="application/ld+json">{JSON.stringify(schema)}</script>
|
|
228
|
+
*/
|
|
229
|
+
|
|
230
|
+
const data = ${JSON.stringify(baseData, null, 2)};
|
|
231
|
+
|
|
232
|
+
const config = {
|
|
233
|
+
geo: {
|
|
234
|
+
contentDensity: 'high' // Optimizes for LLM token efficiency
|
|
235
|
+
}
|
|
236
|
+
};
|
|
237
|
+
|
|
238
|
+
export const ${answers.schemaType}Schema = ${importName}(data, config);
|
|
239
|
+
|
|
240
|
+
// Validation check
|
|
241
|
+
if (!${answers.schemaType}Schema['@context']) {
|
|
242
|
+
throw new Error('Schema generation failed: missing @context');
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
// For testing: log the output
|
|
246
|
+
console.log('Generated JSON-LD:', JSON.stringify(${answers.schemaType}Schema, null, 2));
|
|
247
|
+
`;
|
|
248
|
+
writeFileSync(tsFilePath, tsContent);
|
|
249
|
+
console.log(pc.green(`
|
|
250
|
+
\u2713 Schema generator created: ${pc.bold(tsFilePath)}`));
|
|
251
|
+
}
|
|
252
|
+
console.log(pc.cyan("\n\u2728 Done! \n"));
|
|
253
|
+
if (answers.action === "init") {
|
|
254
|
+
console.log(pc.white(`Next step: Run `) + pc.yellow(`npm install geo-semantic-layer`));
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
main().catch(console.error);
|
|
258
|
+
//# sourceMappingURL=index.js.map
|
|
259
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/cli/index.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["#!/usr/bin/env node\nimport prompts from 'prompts';\nimport { writeFileSync, mkdirSync, existsSync } from 'fs';\nimport { join } from 'path';\nimport pc from 'picocolors';\n\nconsole.log(pc.cyan('\\n🧠 GEO Semantic Layer - Setup & Scaffold\\n'));\n\ninterface Answers {\n action: 'init' | 'generate';\n framework: string;\n entityType: 'Organization' | 'Person' | 'LocalBusiness' | 'Product';\n name: string;\n url: string;\n description: string;\n generateExamples: boolean;\n schemaType: string;\n}\n\nasync function main() {\n const answers = await prompts<keyof Answers>([\n {\n type: 'select',\n name: 'action',\n message: 'What would you like to do?',\n choices: [\n { title: 'Initialize a new configuration', value: 'init' },\n { title: 'Generate a specific schema file', value: 'generate' },\n ]\n },\n // INIT FLOW\n {\n type: (_prev: any) => _prev === 'init' ? 'select' : null,\n name: 'framework',\n message: 'Which framework are you using?',\n choices: [\n { title: 'React / Next.js', value: 'react' },\n { title: 'Vue / Nuxt', value: 'vue' },\n { title: 'Angular', value: 'angular' },\n { title: 'Svelte / SvelteKit', value: 'svelte' },\n { title: 'Astro', value: 'astro' },\n { title: 'Node.js / Express', value: 'node' },\n { title: 'Vanilla JS', value: 'vanilla' }\n ]\n },\n {\n type: (_prev: any, values: any) => values.action === 'init' ? 'select' : null,\n name: 'entityType',\n message: 'What type of entity is your site?',\n choices: [\n { title: 'Organization / Company', value: 'Organization' },\n { title: 'Person / Personal Blog', value: 'Person' },\n { title: 'Local Business (Restaurant, Store)', value: 'LocalBusiness' },\n { title: 'E-commerce / Products', value: 'Product' } // Note: Product is usually for specific pages, but good for defaults\n ]\n },\n {\n type: (_prev: any, values: any) => values.action === 'init' ? 'text' : null,\n name: 'name',\n message: 'Site/Company name:',\n initial: 'My Company'\n },\n {\n type: (_prev: any, values: any) => values.action === 'init' ? 'text' : null,\n name: 'url',\n message: 'Site URL:',\n initial: 'https://example.com'\n },\n {\n type: (_prev: any, values: any) => values.action === 'init' ? 'text' : null,\n name: 'description',\n message: 'Brief description:',\n initial: 'My awesome site'\n },\n {\n type: (_prev: any, values: any) => values.action === 'init' ? 'confirm' : null,\n name: 'generateExamples',\n message: 'Generate example code files?',\n initial: true\n },\n \n // GENERATE FLOW\n {\n type: (_prev: any, values: any) => values.action === 'generate' ? 'select' : null,\n name: 'schemaType',\n message: 'Which schema do you want to generate?',\n choices: [\n { title: 'Article', value: 'article' },\n { title: 'Breadcrumb', value: 'breadcrumb' },\n { title: 'Event', value: 'event' },\n { title: 'FAQ', value: 'faq' },\n { title: 'Local Business', value: 'localbusiness' },\n { title: 'Organization', value: 'organization' },\n { title: 'Person', value: 'person' },\n { title: 'Product', value: 'product' },\n { title: 'WebPage', value: 'webpage' }\n ]\n }\n ]);\n\n if (!answers.action) {\n console.log(pc.red('\\n❌ Operation cancelled\\n'));\n process.exit(0);\n }\n\n const configDir = join(process.cwd(), 'semantic-layer');\n\n // --- HANDLE INIT ---\n if (answers.action === 'init') {\n if (!existsSync(configDir)) {\n mkdirSync(configDir, { recursive: true });\n }\n\n const config = {\n $schema: 'https://raw.githubusercontent.com/bdovenbird/semantic-layer/main/schemas/config.schema.json',\n siteUrl: answers.url,\n framework: answers.framework,\n defaults: {\n type: answers.entityType,\n name: answers.name,\n description: answers.description,\n url: answers.url\n }\n };\n\n const configPath = join(configDir, 'semantic.config.json');\n writeFileSync(configPath, JSON.stringify(config, null, 2));\n console.log(pc.green(`\\n✓ Configuration created: ${pc.bold(configPath)}`));\n\n // Examples\n if (answers.generateExamples) {\n const examplesDir = join(configDir, 'examples');\n if (!existsSync(examplesDir)) {\n mkdirSync(examplesDir, { recursive: true });\n }\n\n let exampleCode = '';\n const fnName = answers.entityType === 'Organization' ? 'generateOrganizationSchema' : 'generatePersonSchema';\n const importLine = `import { ${fnName} } from 'geo-semantic-layer';`;\n \n const schemaOptions = {\n name: answers.name,\n url: answers.url,\n description: answers.description\n };\n\n // Build a more robust \"Power User\" example\n \n const isReactOrSimilar = ['react', 'astro', 'svelte', 'vue'].includes(answers.framework);\n const isAngular = answers.framework === 'angular';\n\n const schemaCallWithConfig = `${fnName}(\n ${JSON.stringify(schemaOptions, null, 2)},\n {\n geo: {\n contentDensity: 'high', // GEO optimization: reduces token usage for LLMs\n }\n }\n)`;\n\n if (isReactOrSimilar) {\n exampleCode = [\n `// ${answers.framework} Integration Example`,\n `// This demonstrates the 3 pillars: Validation, GEO Optimization, and Type Safety`,\n \"\",\n importLine,\n \"\",\n \"/**\",\n \" * Schema configuration with GEO optimization\",\n \" * - Runtime validation via Zod\",\n \" * - Token-optimized for AI models\",\n \" * - Type-safe TypeScript interfaces\",\n \" */\",\n `const schema = ${schemaCallWithConfig};`,\n \"\",\n \"// Insert in your component's <head>:\",\n \"// <script type=\\\"application/ld+json\\\">\",\n \"// {JSON.stringify(schema)}\",\n \"// </script>\",\n \"\",\n \"export default schema;\"\n ].join(\"\\\\n\");\n } else if (isAngular) {\n exampleCode = [\n `// Angular Integration Example`,\n importLine,\n \"\",\n \"import { Component } from '@angular/core';\",\n \"\",\n \"@Component({\",\n \" selector: 'app-root',\",\n \" template: `<div [innerHTML]=\\\"schemaScript\\\"></div>`\",\n \"})\",\n \"export class AppComponent {\",\n ` schema = ${schemaCallWithConfig};`,\n \"\",\n \" get schemaScript() {\",\n \" return `<script type=\\\"application/ld+json\\\">${JSON.stringify(this.schema)}</script>`;\",\n \" }\",\n \"}\"\n ].join(\"\\\\n\");\n } else {\n exampleCode = [\n `// ${answers.framework} Integration Example`,\n importLine,\n \"\",\n \"/**\",\n \" * GEO-optimized schema generation\",\n \" * - Validated with Zod at runtime\",\n \" * - Optimized for AI model consumption\",\n \" */\",\n `const schema = ${schemaCallWithConfig};`,\n \"\",\n \"// Output for verification\",\n \"console.log('Generated Schema:', JSON.stringify(schema, null, 2));\",\n \"\",\n \"export default schema;\"\n ].join(\"\\\\n\");\n }\n\n writeFileSync(join(examplesDir, `example.${answers.framework === 'angular' ? 'ts' : 'js'}`), exampleCode);\n console.log(pc.green(`✓ Example created: ${pc.bold(`semantic-layer/examples/example.${answers.framework === 'angular' ? 'ts' : 'js'}`)}`));\n }\n }\n\n // --- HANDLE GENERATE ---\n if (answers.action === 'generate') {\n if (!existsSync(configDir)) {\n mkdirSync(configDir, { recursive: true });\n }\n \n const tsFilename = `${answers.schemaType}.ts`;\n const tsFilePath = join(configDir, tsFilename);\n const importName = `generate${answers.schemaType.charAt(0).toUpperCase() + answers.schemaType.slice(1)}Schema`;\n \n // Configuración base sugerida según el tipo\n const baseData: any = {\n name: answers.name || 'My Entity',\n url: answers.url || 'https://example.com',\n };\n\n if (answers.schemaType === 'article') {\n baseData.headline = 'My Article Headline';\n baseData.author = 'Author Name';\n baseData.datePublished = new Date().toISOString().split('T')[0];\n }\n\n const tsContent = `import { ${importName} } from 'geo-semantic-layer';\n\n/**\n * Generated ${answers.schemaType} schema with GEO optimization\n *\n * This schema is:\n * - Runtime validated with Zod\n * - Optimized for AI model consumption (GEO Engine)\n * - Compatible with all JavaScript environments\n *\n * Usage:\n * 1. Update the data object with your actual values\n * 2. Import and use in your application\n * 3. Insert as <script type=\"application/ld+json\">{JSON.stringify(schema)}</script>\n */\n\nconst data = ${JSON.stringify(baseData, null, 2)};\n\nconst config = {\n geo: {\n contentDensity: 'high' // Optimizes for LLM token efficiency\n }\n};\n\nexport const ${answers.schemaType}Schema = ${importName}(data, config);\n\n// Validation check\nif (!${answers.schemaType}Schema['@context']) {\n throw new Error('Schema generation failed: missing @context');\n}\n\n// For testing: log the output\nconsole.log('Generated JSON-LD:', JSON.stringify(${answers.schemaType}Schema, null, 2));\n`;\n\n writeFileSync(tsFilePath, tsContent);\n console.log(pc.green(`\\n✓ Schema generator created: ${pc.bold(tsFilePath)}`));\n }\n\n console.log(pc.cyan('\\n✨ Done! \\n'));\n if (answers.action === 'init') {\n console.log(pc.white(`Next step: Run `) + pc.yellow(`npm install geo-semantic-layer`));\n }\n}\n\nmain().catch(console.error);\n"]}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "geo-semantic-layer",
|
|
3
|
-
"version": "2.0.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "2.0.3",
|
|
4
|
+
"description": "Enterprise-grade structured data (JSON-LD) generator with runtime validation and Generative Engine Optimization (GEO) capabilities. Includes CLI for rapid scaffolding.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"seo",
|
|
7
7
|
"geo",
|
|
@@ -19,7 +19,11 @@
|
|
|
19
19
|
"chatgpt",
|
|
20
20
|
"perplexity",
|
|
21
21
|
"universal",
|
|
22
|
-
"zero-dependencies"
|
|
22
|
+
"zero-dependencies",
|
|
23
|
+
"validation",
|
|
24
|
+
"cli",
|
|
25
|
+
"scaffolding",
|
|
26
|
+
"llm-optimization"
|
|
23
27
|
],
|
|
24
28
|
"homepage": "https://github.com/bdovenbird/semantic-layer#readme",
|
|
25
29
|
"repository": {
|
|
@@ -50,6 +54,9 @@
|
|
|
50
54
|
"main": "./dist/index.js",
|
|
51
55
|
"module": "./dist/index.js",
|
|
52
56
|
"types": "./dist/index.d.ts",
|
|
57
|
+
"bin": {
|
|
58
|
+
"geo-semantic-layer": "./dist/cli/index.js"
|
|
59
|
+
},
|
|
53
60
|
"files": [
|
|
54
61
|
"dist",
|
|
55
62
|
"README.md",
|
|
@@ -71,10 +78,14 @@
|
|
|
71
78
|
"prepublishOnly": "npm run build"
|
|
72
79
|
},
|
|
73
80
|
"dependencies": {
|
|
81
|
+
"commander": "14.0.2",
|
|
82
|
+
"picocolors": "1.1.1",
|
|
83
|
+
"prompts": "2.4.2",
|
|
74
84
|
"zod": "^3.22.4"
|
|
75
85
|
},
|
|
76
86
|
"devDependencies": {
|
|
77
87
|
"@types/node": "^20.11.5",
|
|
88
|
+
"@types/prompts": "2.4.9",
|
|
78
89
|
"@typescript-eslint/eslint-plugin": "^6.19.0",
|
|
79
90
|
"@typescript-eslint/parser": "^6.19.0",
|
|
80
91
|
"@vitest/coverage-v8": "^1.2.1",
|