@edtools/cli 0.1.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 +219 -0
- package/bin/edtools.js +9 -0
- package/dist/adapters/html/index.d.ts +18 -0
- package/dist/adapters/html/index.d.ts.map +1 -0
- package/dist/adapters/html/index.js +132 -0
- package/dist/adapters/html/index.js.map +1 -0
- package/dist/chunk-6534GCE5.js +458 -0
- package/dist/cli/commands/generate.d.ts +9 -0
- package/dist/cli/commands/generate.d.ts.map +1 -0
- package/dist/cli/commands/generate.js +101 -0
- package/dist/cli/commands/generate.js.map +1 -0
- package/dist/cli/commands/init.d.ts +6 -0
- package/dist/cli/commands/init.d.ts.map +1 -0
- package/dist/cli/commands/init.js +160 -0
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/index.d.ts +1 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +286 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/core/generator.d.ts +14 -0
- package/dist/core/generator.d.ts.map +1 -0
- package/dist/core/generator.js +241 -0
- package/dist/core/generator.js.map +1 -0
- package/dist/index.d.ts +170 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/dist/types/adapter.d.ts +22 -0
- package/dist/types/adapter.d.ts.map +1 -0
- package/dist/types/adapter.js +24 -0
- package/dist/types/adapter.js.map +1 -0
- package/dist/types/content.d.ts +118 -0
- package/dist/types/content.d.ts.map +1 -0
- package/dist/types/content.js +2 -0
- package/dist/types/content.js.map +1 -0
- package/dist/types/index.d.ts +3 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +3 -0
- package/dist/types/index.js.map +1 -0
- package/package.json +51 -0
package/README.md
ADDED
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
# @edtools/cli
|
|
2
|
+
|
|
3
|
+
> Generate SEO-optimized content for LLM discovery
|
|
4
|
+
|
|
5
|
+
Make your product discoverable by AI assistants like Claude and ChatGPT through semantic search and SEO-optimized static pages.
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
- ✅ **Framework Agnostic** - Works with HTML, Next.js, and more
|
|
10
|
+
- ✅ **AI-Powered** - Uses Claude to generate high-quality content
|
|
11
|
+
- ✅ **SEO Optimized** - Built-in SEO scoring and Schema.org markup
|
|
12
|
+
- ✅ **Local Processing** - No centralized database, everything runs locally
|
|
13
|
+
- ✅ **Anti-Spam Safeguards** - Prevents Google penalties with rate limiting
|
|
14
|
+
- ✅ **Extensible** - Plugin system for custom adapters
|
|
15
|
+
|
|
16
|
+
## Quick Start
|
|
17
|
+
|
|
18
|
+
### Installation
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
npm install -g @edtools/cli
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
### Setup
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
cd your-project
|
|
28
|
+
edtools init
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
This will:
|
|
32
|
+
1. Analyze your landing page
|
|
33
|
+
2. Create `edtools.config.js`
|
|
34
|
+
3. Prompt for product information
|
|
35
|
+
|
|
36
|
+
### Generate Content
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
# Set your Anthropic API key
|
|
40
|
+
export ANTHROPIC_API_KEY=sk-ant-...
|
|
41
|
+
|
|
42
|
+
# Generate 3 blog posts
|
|
43
|
+
edtools generate
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## How It Works
|
|
47
|
+
|
|
48
|
+
```
|
|
49
|
+
Your Landing Page
|
|
50
|
+
↓
|
|
51
|
+
edtools init (analyzes & creates config)
|
|
52
|
+
↓
|
|
53
|
+
edtools generate (creates blog posts)
|
|
54
|
+
↓
|
|
55
|
+
Static HTML files optimized for:
|
|
56
|
+
- Google SEO
|
|
57
|
+
- AI crawlers (Claude, ChatGPT)
|
|
58
|
+
- Schema.org markup
|
|
59
|
+
- llms.txt format
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## CLI Commands
|
|
63
|
+
|
|
64
|
+
### `edtools init`
|
|
65
|
+
|
|
66
|
+
Initialize edtools in your project.
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
edtools init [options]
|
|
70
|
+
|
|
71
|
+
Options:
|
|
72
|
+
-p, --path <path> Project path (default: current directory)
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### `edtools generate`
|
|
76
|
+
|
|
77
|
+
Generate SEO-optimized blog posts.
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
edtools generate [options]
|
|
81
|
+
|
|
82
|
+
Options:
|
|
83
|
+
-n, --posts <number> Number of posts (default: 3, max: 10)
|
|
84
|
+
-t, --topics <topics...> Specific topics to write about
|
|
85
|
+
-o, --output <dir> Output directory (default: ./blog)
|
|
86
|
+
--api-key <key> Anthropic API key
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
**Example:**
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
edtools generate -n 5 -o ./content/blog
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### `edtools config`
|
|
96
|
+
|
|
97
|
+
View or set configuration.
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
edtools config [options]
|
|
101
|
+
|
|
102
|
+
Options:
|
|
103
|
+
--set-api-key <key> Set Anthropic API key
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## Configuration
|
|
107
|
+
|
|
108
|
+
The `edtools.config.js` file contains your product information:
|
|
109
|
+
|
|
110
|
+
```javascript
|
|
111
|
+
module.exports = {
|
|
112
|
+
product: {
|
|
113
|
+
name: "My Product",
|
|
114
|
+
tagline: "One-line description",
|
|
115
|
+
description: "Longer description...",
|
|
116
|
+
category: "productivity",
|
|
117
|
+
websiteUrl: "https://myproduct.com",
|
|
118
|
+
pricingModel: "freemium",
|
|
119
|
+
features: [
|
|
120
|
+
"Feature 1",
|
|
121
|
+
"Feature 2",
|
|
122
|
+
],
|
|
123
|
+
},
|
|
124
|
+
|
|
125
|
+
content: {
|
|
126
|
+
outputDir: './blog',
|
|
127
|
+
generateBlog: true,
|
|
128
|
+
},
|
|
129
|
+
|
|
130
|
+
seo: {
|
|
131
|
+
siteMapPath: './sitemap.xml',
|
|
132
|
+
robotsPath: './robots.txt',
|
|
133
|
+
allowAICrawlers: true,
|
|
134
|
+
},
|
|
135
|
+
};
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
## Architecture
|
|
139
|
+
|
|
140
|
+
### Framework Agnostic Design
|
|
141
|
+
|
|
142
|
+
Edtools uses a 3-layer architecture:
|
|
143
|
+
|
|
144
|
+
1. **Core Layer** - Generates content in universal JSON format
|
|
145
|
+
2. **Adapter Layer** - Converts JSON to framework-specific code
|
|
146
|
+
3. **Template Layer** - Renders final output
|
|
147
|
+
|
|
148
|
+
**Current Adapters:**
|
|
149
|
+
- ✅ HTML (static)
|
|
150
|
+
- 🔄 Next.js (coming in v1.1)
|
|
151
|
+
- 🔄 Markdown (coming in v1.1)
|
|
152
|
+
|
|
153
|
+
### Avoiding Google Penalties
|
|
154
|
+
|
|
155
|
+
Edtools includes safeguards to prevent spam detection:
|
|
156
|
+
|
|
157
|
+
- **Rate Limiting**: Maximum 10 posts per run
|
|
158
|
+
- **Spacing Recommendations**: Warns if generating too quickly
|
|
159
|
+
- **Human Review**: Generated content requires review before publishing
|
|
160
|
+
- **SEO Scoring**: Validates content quality
|
|
161
|
+
- **No Keyword Stuffing**: Natural language generation
|
|
162
|
+
|
|
163
|
+
## Best Practices
|
|
164
|
+
|
|
165
|
+
1. **Generate Slowly**: 3-5 posts per week maximum
|
|
166
|
+
2. **Review Content**: Always add personal experience/expertise
|
|
167
|
+
3. **Space Publications**: Wait 3-7 days between batches
|
|
168
|
+
4. **Verify Facts**: Check all statistics and claims
|
|
169
|
+
5. **Add Examples**: Include real-world use cases
|
|
170
|
+
|
|
171
|
+
## API Usage (Programmatic)
|
|
172
|
+
|
|
173
|
+
```typescript
|
|
174
|
+
import { ContentGenerator } from '@edtools/cli';
|
|
175
|
+
|
|
176
|
+
const generator = new ContentGenerator(apiKey);
|
|
177
|
+
|
|
178
|
+
const result = await generator.generate({
|
|
179
|
+
productInfo: {
|
|
180
|
+
name: "My Product",
|
|
181
|
+
category: "productivity",
|
|
182
|
+
// ...
|
|
183
|
+
},
|
|
184
|
+
outputDir: './blog',
|
|
185
|
+
count: 3,
|
|
186
|
+
});
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
## Requirements
|
|
190
|
+
|
|
191
|
+
- Node.js 18+
|
|
192
|
+
- Anthropic API key ([get one here](https://console.anthropic.com/))
|
|
193
|
+
|
|
194
|
+
## Roadmap
|
|
195
|
+
|
|
196
|
+
- [ ] **v1.1**: MCP Server for Claude Code integration
|
|
197
|
+
- [ ] **v1.1**: Next.js adapter
|
|
198
|
+
- [ ] **v1.1**: Markdown adapter
|
|
199
|
+
- [ ] **v1.2**: Local embeddings for duplicate detection
|
|
200
|
+
- [ ] **v1.3**: Shopify adapter
|
|
201
|
+
- [ ] **v2.0**: Dashboard web interface
|
|
202
|
+
|
|
203
|
+
## Contributing
|
|
204
|
+
|
|
205
|
+
Contributions are welcome! Please see [CONTRIBUTING.md](CONTRIBUTING.md).
|
|
206
|
+
|
|
207
|
+
## License
|
|
208
|
+
|
|
209
|
+
MIT © Edtools Team
|
|
210
|
+
|
|
211
|
+
## Links
|
|
212
|
+
|
|
213
|
+
- **Documentation**: [https://docs.edtools.dev](https://docs.edtools.dev)
|
|
214
|
+
- **GitHub**: [https://github.com/edtools/cli](https://github.com/edtools/cli)
|
|
215
|
+
- **Issues**: [https://github.com/edtools/cli/issues](https://github.com/edtools/cli/issues)
|
|
216
|
+
|
|
217
|
+
---
|
|
218
|
+
|
|
219
|
+
**Made with ❤️ to help products get discovered by AI assistants**
|
package/bin/edtools.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Adapter, BlogPostContent } from '../../types/index.js';
|
|
2
|
+
export declare class HTMLAdapter implements Adapter {
|
|
3
|
+
name: string;
|
|
4
|
+
private templatePath;
|
|
5
|
+
constructor();
|
|
6
|
+
detect(projectPath: string): Promise<boolean>;
|
|
7
|
+
render(content: BlogPostContent): Promise<string>;
|
|
8
|
+
write(output: string, outputPath: string): Promise<void>;
|
|
9
|
+
getFileExtension(): string;
|
|
10
|
+
transformPath(basePath: string): string;
|
|
11
|
+
private markdownToHTML;
|
|
12
|
+
private renderSectionContent;
|
|
13
|
+
private renderComparisonTable;
|
|
14
|
+
private renderList;
|
|
15
|
+
private renderCode;
|
|
16
|
+
private escapeHtml;
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/adapters/html/index.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAEhE,qBAAa,WAAY,YAAW,OAAO;IACzC,IAAI,SAAU;IACd,OAAO,CAAC,YAAY,CAAS;;IAOvB,MAAM,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAe7C,MAAM,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC;IA2BjD,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQ9D,gBAAgB,IAAI,MAAM;IAI1B,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM;YAWzB,cAAc;YAOd,oBAAoB;IAsBlC,OAAO,CAAC,qBAAqB;IAiC7B,OAAO,CAAC,UAAU;IAyBlB,OAAO,CAAC,UAAU;IAoBlB,OAAO,CAAC,UAAU;CAUnB"}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import fs from 'fs-extra';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import ejs from 'ejs';
|
|
4
|
+
import { marked } from 'marked';
|
|
5
|
+
export class HTMLAdapter {
|
|
6
|
+
name = 'html';
|
|
7
|
+
templatePath;
|
|
8
|
+
constructor() {
|
|
9
|
+
this.templatePath = path.join(__dirname, 'templates', 'blog-post.html.ejs');
|
|
10
|
+
}
|
|
11
|
+
async detect(projectPath) {
|
|
12
|
+
try {
|
|
13
|
+
const files = await fs.readdir(projectPath);
|
|
14
|
+
const hasHtml = files.some(f => f.endsWith('.html'));
|
|
15
|
+
const hasIndexHtml = await fs.pathExists(path.join(projectPath, 'index.html'));
|
|
16
|
+
return hasHtml || hasIndexHtml;
|
|
17
|
+
}
|
|
18
|
+
catch (error) {
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
async render(content) {
|
|
23
|
+
const template = await fs.readFile(this.templatePath, 'utf-8');
|
|
24
|
+
const templateData = {
|
|
25
|
+
metadata: content.metadata,
|
|
26
|
+
schemaOrg: JSON.stringify(content.schemaOrg, null, 2),
|
|
27
|
+
intro: await this.markdownToHTML(content.content.intro),
|
|
28
|
+
sections: await Promise.all(content.content.sections.map(async (section) => ({
|
|
29
|
+
...section,
|
|
30
|
+
content: await this.renderSectionContent(section),
|
|
31
|
+
}))),
|
|
32
|
+
conclusion: await this.markdownToHTML(content.content.conclusion),
|
|
33
|
+
cta: content.content.cta,
|
|
34
|
+
relatedPosts: content.relatedPosts || [],
|
|
35
|
+
seoScore: content.seo.score,
|
|
36
|
+
};
|
|
37
|
+
const html = ejs.render(template, templateData);
|
|
38
|
+
return html;
|
|
39
|
+
}
|
|
40
|
+
async write(output, outputPath) {
|
|
41
|
+
await fs.ensureDir(path.dirname(outputPath));
|
|
42
|
+
await fs.writeFile(outputPath, output, 'utf-8');
|
|
43
|
+
}
|
|
44
|
+
getFileExtension() {
|
|
45
|
+
return '.html';
|
|
46
|
+
}
|
|
47
|
+
transformPath(basePath) {
|
|
48
|
+
if (!basePath.endsWith('.html')) {
|
|
49
|
+
return basePath + '/index.html';
|
|
50
|
+
}
|
|
51
|
+
return basePath;
|
|
52
|
+
}
|
|
53
|
+
async markdownToHTML(markdown) {
|
|
54
|
+
return marked(markdown);
|
|
55
|
+
}
|
|
56
|
+
async renderSectionContent(section) {
|
|
57
|
+
switch (section.type) {
|
|
58
|
+
case 'text':
|
|
59
|
+
return await this.markdownToHTML(section.content);
|
|
60
|
+
case 'comparison':
|
|
61
|
+
return this.renderComparisonTable(section.data);
|
|
62
|
+
case 'list':
|
|
63
|
+
return this.renderList(section.data);
|
|
64
|
+
case 'code':
|
|
65
|
+
return this.renderCode(section.data);
|
|
66
|
+
default:
|
|
67
|
+
return await this.markdownToHTML(section.content);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
renderComparisonTable(data) {
|
|
71
|
+
if (!data || !data.headers || !data.rows) {
|
|
72
|
+
return '';
|
|
73
|
+
}
|
|
74
|
+
let html = '<table class="comparison-table">\n';
|
|
75
|
+
html += ' <thead>\n <tr>\n';
|
|
76
|
+
data.headers.forEach((header) => {
|
|
77
|
+
html += ` <th>${header}</th>\n`;
|
|
78
|
+
});
|
|
79
|
+
html += ' </tr>\n </thead>\n';
|
|
80
|
+
html += ' <tbody>\n';
|
|
81
|
+
data.rows.forEach((row) => {
|
|
82
|
+
html += ' <tr>\n';
|
|
83
|
+
row.forEach((cell) => {
|
|
84
|
+
html += ` <td>${cell}</td>\n`;
|
|
85
|
+
});
|
|
86
|
+
html += ' </tr>\n';
|
|
87
|
+
});
|
|
88
|
+
html += ' </tbody>\n';
|
|
89
|
+
html += '</table>';
|
|
90
|
+
return html;
|
|
91
|
+
}
|
|
92
|
+
renderList(data) {
|
|
93
|
+
if (!data || !data.items) {
|
|
94
|
+
return '';
|
|
95
|
+
}
|
|
96
|
+
const tag = data.ordered ? 'ol' : 'ul';
|
|
97
|
+
let html = `<${tag} class="content-list">\n`;
|
|
98
|
+
data.items.forEach((item) => {
|
|
99
|
+
html += ' <li>\n';
|
|
100
|
+
html += ` <strong>${item.title}</strong>\n`;
|
|
101
|
+
if (item.description) {
|
|
102
|
+
html += ` <p>${item.description}</p>\n`;
|
|
103
|
+
}
|
|
104
|
+
html += ' </li>\n';
|
|
105
|
+
});
|
|
106
|
+
html += `</${tag}>`;
|
|
107
|
+
return html;
|
|
108
|
+
}
|
|
109
|
+
renderCode(data) {
|
|
110
|
+
if (!data || !data.code) {
|
|
111
|
+
return '';
|
|
112
|
+
}
|
|
113
|
+
let html = '<div class="code-block">\n';
|
|
114
|
+
if (data.caption) {
|
|
115
|
+
html += ` <div class="code-caption">${data.caption}</div>\n`;
|
|
116
|
+
}
|
|
117
|
+
html += ` <pre><code class="language-${data.language || 'plaintext'}">${this.escapeHtml(data.code)}</code></pre>\n`;
|
|
118
|
+
html += '</div>';
|
|
119
|
+
return html;
|
|
120
|
+
}
|
|
121
|
+
escapeHtml(text) {
|
|
122
|
+
const map = {
|
|
123
|
+
'&': '&',
|
|
124
|
+
'<': '<',
|
|
125
|
+
'>': '>',
|
|
126
|
+
'"': '"',
|
|
127
|
+
"'": '''
|
|
128
|
+
};
|
|
129
|
+
return text.replace(/[&<>"']/g, (m) => map[m]);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/adapters/html/index.ts"],"names":[],"mappings":"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"}
|