@opendirectory.dev/skills 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/.claude/skills/claude-md-generator/.env.example +7 -0
- package/.claude/skills/claude-md-generator/README.md +78 -0
- package/.claude/skills/claude-md-generator/SKILL.md +248 -0
- package/.claude/skills/claude-md-generator/evals/evals.json +35 -0
- package/.claude/skills/claude-md-generator/references/section-guide.md +175 -0
- package/dist/e2e.test.d.ts +1 -0
- package/dist/e2e.test.js +62 -0
- package/dist/fs-adapters.d.ts +4 -0
- package/dist/fs-adapters.js +101 -0
- package/dist/fs-adapters.test.d.ts +1 -0
- package/dist/fs-adapters.test.js +108 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +211 -0
- package/dist/transformers.d.ts +6 -0
- package/dist/transformers.js +2 -0
- package/package.json +25 -0
- package/registry.json +226 -0
- package/skills/blog-cover-image-cli/.github/workflows/publish.yml +19 -0
- package/skills/blog-cover-image-cli/LICENSE +15 -0
- package/skills/blog-cover-image-cli/README.md +126 -0
- package/skills/blog-cover-image-cli/SKILL.md +7 -0
- package/skills/blog-cover-image-cli/agent-skill/blog-cover-generator/README.md +30 -0
- package/skills/blog-cover-image-cli/agent-skill/blog-cover-generator/SKILL.md +72 -0
- package/skills/blog-cover-image-cli/bin/cli.js +226 -0
- package/skills/blog-cover-image-cli/examples/100x_UX_Research_AI_Agent.png +0 -0
- package/skills/blog-cover-image-cli/examples/Firecrawl-supabase-bolt.png +0 -0
- package/skills/blog-cover-image-cli/examples/Git-City_Case_study_Cover_Image.jpg +0 -0
- package/skills/blog-cover-image-cli/examples/THE DISTRIBUTION LAYER (2).png +0 -0
- package/skills/blog-cover-image-cli/examples/canva-perplexity-duolingo-cover-image.png +0 -0
- package/skills/blog-cover-image-cli/examples/gamma-mistral-veed.png +0 -0
- package/skills/blog-cover-image-cli/examples/server-survival-case-study-cover-image(1).png +0 -0
- package/skills/blog-cover-image-cli/examples/viral-meme-automation.png +0 -0
- package/skills/blog-cover-image-cli/index.js +2 -0
- package/skills/blog-cover-image-cli/package-lock.json +2238 -0
- package/skills/blog-cover-image-cli/package.json +37 -0
- package/skills/blog-cover-image-cli/src/geminiGenerator.js +126 -0
- package/skills/blog-cover-image-cli/src/imageValidator.js +54 -0
- package/skills/blog-cover-image-cli/src/logoFetcher.js +86 -0
- package/skills/claude-md-generator/.env.example +7 -0
- package/skills/claude-md-generator/README.md +78 -0
- package/skills/claude-md-generator/SKILL.md +254 -0
- package/skills/claude-md-generator/evals/evals.json +35 -0
- package/skills/claude-md-generator/references/section-guide.md +175 -0
- package/skills/cook-the-blog/README.md +86 -0
- package/skills/cook-the-blog/SKILL.md +130 -0
- package/skills/dependency-update-bot/.env.example +13 -0
- package/skills/dependency-update-bot/README.md +101 -0
- package/skills/dependency-update-bot/SKILL.md +376 -0
- package/skills/dependency-update-bot/evals/evals.json +45 -0
- package/skills/dependency-update-bot/references/changelog-patterns.md +201 -0
- package/skills/docs-from-code/.env.example +13 -0
- package/skills/docs-from-code/README.md +97 -0
- package/skills/docs-from-code/SKILL.md +160 -0
- package/skills/docs-from-code/evals/evals.json +29 -0
- package/skills/docs-from-code/references/extraction-guide.md +174 -0
- package/skills/docs-from-code/references/output-template.md +135 -0
- package/skills/docs-from-code/scripts/extract_py.py +238 -0
- package/skills/docs-from-code/scripts/extract_ts.ts +284 -0
- package/skills/docs-from-code/scripts/package.json +18 -0
- package/skills/explain-this-pr/README.md +74 -0
- package/skills/explain-this-pr/SKILL.md +130 -0
- package/skills/explain-this-pr/evals/evals.json +35 -0
- package/skills/google-trends-api-skills/README.md +78 -0
- package/skills/google-trends-api-skills/SKILL.md +7 -0
- package/skills/google-trends-api-skills/google-trends-api/SKILL.md +163 -0
- package/skills/google-trends-api-skills/google-trends-api/references/api-responses.md +188 -0
- package/skills/google-trends-api-skills/google-trends-api/scripts/discover_keywords.py +344 -0
- package/skills/google-trends-api-skills/seo-keyword-research/SKILL.md +205 -0
- package/skills/google-trends-api-skills/seo-keyword-research/references/keyword-placement-guide.md +89 -0
- package/skills/google-trends-api-skills/seo-keyword-research/references/tech-blog-examples.md +207 -0
- package/skills/google-trends-api-skills/seo-keyword-research/scripts/blog_seo_research.py +373 -0
- package/skills/hackernews-intel/.env.example +33 -0
- package/skills/hackernews-intel/README.md +161 -0
- package/skills/hackernews-intel/SKILL.md +156 -0
- package/skills/hackernews-intel/evals/evals.json +35 -0
- package/skills/hackernews-intel/package.json +15 -0
- package/skills/hackernews-intel/scripts/monitor-hn.js +258 -0
- package/skills/kill-the-standup/.env.example +22 -0
- package/skills/kill-the-standup/README.md +84 -0
- package/skills/kill-the-standup/SKILL.md +169 -0
- package/skills/kill-the-standup/evals/evals.json +35 -0
- package/skills/kill-the-standup/references/standup-format.md +102 -0
- package/skills/linkedin-post-generator/.env.example +14 -0
- package/skills/linkedin-post-generator/README.md +107 -0
- package/skills/linkedin-post-generator/SKILL.md +228 -0
- package/skills/linkedin-post-generator/evals/evals.json +35 -0
- package/skills/linkedin-post-generator/references/linkedin-format.md +216 -0
- package/skills/linkedin-post-generator/references/output-template.md +154 -0
- package/skills/llms-txt-generator/.env.example +18 -0
- package/skills/llms-txt-generator/README.md +142 -0
- package/skills/llms-txt-generator/SKILL.md +176 -0
- package/skills/llms-txt-generator/evals/evals.json +35 -0
- package/skills/llms-txt-generator/references/llms-txt-spec.md +88 -0
- package/skills/llms-txt-generator/references/output-template.md +76 -0
- package/skills/llms-txt-generator/test-output/genzcareer.in/llms.txt +31 -0
- package/skills/luma-attendees-scraper/README.md +170 -0
- package/skills/luma-attendees-scraper/SKILL.md +7 -0
- package/skills/luma-attendees-scraper/luma_attendees_export.js +223 -0
- package/skills/meeting-brief-generator/.env.example +21 -0
- package/skills/meeting-brief-generator/README.md +90 -0
- package/skills/meeting-brief-generator/SKILL.md +275 -0
- package/skills/meeting-brief-generator/evals/evals.json +35 -0
- package/skills/meeting-brief-generator/references/brief-format.md +114 -0
- package/skills/meeting-brief-generator/references/output-template.md +150 -0
- package/skills/meta-ads-skill/README.md +100 -0
- package/skills/meta-ads-skill/SKILL.md +7 -0
- package/skills/meta-ads-skill/meta-ads-skill/SKILL.md +41 -0
- package/skills/meta-ads-skill/meta-ads-skill/references/report_templates.md +47 -0
- package/skills/meta-ads-skill/meta-ads-skill/references/workflows.md +51 -0
- package/skills/meta-ads-skill/meta-ads-skill/scripts/auth_check.py +22 -0
- package/skills/meta-ads-skill/meta-ads-skill/scripts/formatters.py +46 -0
- package/skills/newsletter-digest/.env.example +20 -0
- package/skills/newsletter-digest/README.md +147 -0
- package/skills/newsletter-digest/SKILL.md +221 -0
- package/skills/newsletter-digest/evals/evals.json +35 -0
- package/skills/newsletter-digest/feeds.json +7 -0
- package/skills/newsletter-digest/package.json +15 -0
- package/skills/newsletter-digest/references/digest-format.md +123 -0
- package/skills/newsletter-digest/references/output-template.md +136 -0
- package/skills/newsletter-digest/scripts/fetch-feeds.js +141 -0
- package/skills/newsletter-digest/scripts/ghost-publish.js +147 -0
- package/skills/noise2blog/.env.example +16 -0
- package/skills/noise2blog/README.md +107 -0
- package/skills/noise2blog/SKILL.md +229 -0
- package/skills/noise2blog/evals/evals.json +35 -0
- package/skills/noise2blog/references/blog-format.md +188 -0
- package/skills/noise2blog/references/output-template.md +184 -0
- package/skills/outreach-sequence-builder/.env.example +12 -0
- package/skills/outreach-sequence-builder/README.md +108 -0
- package/skills/outreach-sequence-builder/SKILL.md +248 -0
- package/skills/outreach-sequence-builder/evals/evals.json +36 -0
- package/skills/outreach-sequence-builder/references/output-template.md +171 -0
- package/skills/outreach-sequence-builder/references/sequence-format.md +167 -0
- package/skills/outreach-sequence-builder/references/signal-playbook.md +117 -0
- package/skills/position-me/README.md +71 -0
- package/skills/position-me/SKILL.md +7 -0
- package/skills/position-me/position-me/SKILL.md +50 -0
- package/skills/position-me/position-me/references/EVALUATION_SOP.md +40 -0
- package/skills/position-me/position-me/references/REPORT_TEMPLATE.md +58 -0
- package/skills/position-me/position-me/scripts/extract_links.py +49 -0
- package/skills/pr-description-writer/README.md +81 -0
- package/skills/pr-description-writer/SKILL.md +141 -0
- package/skills/pr-description-writer/evals/evals.json +35 -0
- package/skills/pr-description-writer/references/pr-format-guide.md +145 -0
- package/skills/producthunt-launch-kit/.env.example +7 -0
- package/skills/producthunt-launch-kit/README.md +95 -0
- package/skills/producthunt-launch-kit/SKILL.md +380 -0
- package/skills/producthunt-launch-kit/evals/evals.json +35 -0
- package/skills/producthunt-launch-kit/references/copy-rules.md +124 -0
- package/skills/reddit-icp-monitor/.env.example +16 -0
- package/skills/reddit-icp-monitor/README.md +117 -0
- package/skills/reddit-icp-monitor/SKILL.md +271 -0
- package/skills/reddit-icp-monitor/evals/evals.json +40 -0
- package/skills/reddit-icp-monitor/references/icp-format.md +131 -0
- package/skills/reddit-icp-monitor/references/reply-rules.md +110 -0
- package/skills/reddit-post-engine/.env.example +13 -0
- package/skills/reddit-post-engine/README.md +103 -0
- package/skills/reddit-post-engine/SKILL.md +303 -0
- package/skills/reddit-post-engine/evals/evals.json +35 -0
- package/skills/reddit-post-engine/references/subreddit-playbook.md +156 -0
- package/skills/schema-markup-generator/.env.example +19 -0
- package/skills/schema-markup-generator/README.md +114 -0
- package/skills/schema-markup-generator/SKILL.md +192 -0
- package/skills/schema-markup-generator/evals/evals.json +35 -0
- package/skills/schema-markup-generator/references/json-ld-spec.md +263 -0
- package/skills/schema-markup-generator/references/output-template.md +556 -0
- package/skills/show-hn-writer/.env.example +14 -0
- package/skills/show-hn-writer/README.md +88 -0
- package/skills/show-hn-writer/SKILL.md +303 -0
- package/skills/show-hn-writer/evals/evals.json +35 -0
- package/skills/show-hn-writer/references/hn-rules.md +74 -0
- package/skills/show-hn-writer/references/title-formulas.md +93 -0
- package/skills/stargazer/README.md +79 -0
- package/skills/stargazer/SKILL.md +7 -0
- package/skills/stargazer/stargazer-skill/SKILL.md +58 -0
- package/skills/stargazer/stargazer-skill/assets/.env.example +18 -0
- package/skills/stargazer/stargazer-skill/scripts/convert_to_csv.py +63 -0
- package/skills/stargazer/stargazer-skill/scripts/count_emails.py +52 -0
- package/skills/stargazer/stargazer-skill/scripts/stargazer_deep_extractor.py +450 -0
- package/skills/tweet-thread-from-blog/.env.example +14 -0
- package/skills/tweet-thread-from-blog/README.md +109 -0
- package/skills/tweet-thread-from-blog/SKILL.md +177 -0
- package/skills/tweet-thread-from-blog/evals/evals.json +35 -0
- package/skills/tweet-thread-from-blog/references/output-template.md +193 -0
- package/skills/tweet-thread-from-blog/references/thread-format.md +107 -0
- package/skills/twitter-GTM-find-skill/README.md +43 -0
- package/skills/twitter-GTM-find-skill/SKILL.md +7 -0
- package/skills/twitter-GTM-find-skill/twitter-GTM-find/SKILL.md +37 -0
- package/skills/twitter-GTM-find-skill/twitter-GTM-find/references/icp-checklist.md +35 -0
- package/skills/twitter-GTM-find-skill/twitter-GTM-find/scripts/package.json +23 -0
- package/skills/twitter-GTM-find-skill/twitter-GTM-find/scripts/run_pipeline.sh +8 -0
- package/skills/twitter-GTM-find-skill/twitter-GTM-find/scripts/src/debug.ts +23 -0
- package/skills/twitter-GTM-find-skill/twitter-GTM-find/scripts/src/extractor.ts +79 -0
- package/skills/twitter-GTM-find-skill/twitter-GTM-find/scripts/src/icp-filter.ts +87 -0
- package/skills/twitter-GTM-find-skill/twitter-GTM-find/scripts/src/index.ts +94 -0
- package/skills/twitter-GTM-find-skill/twitter-GTM-find/scripts/src/scraper.ts +41 -0
- package/skills/twitter-GTM-find-skill/twitter-GTM-find/scripts/tsconfig.json +13 -0
- package/skills/yc-intent-radar-skill/README.md +39 -0
- package/skills/yc-intent-radar-skill/SKILL.md +7 -0
- package/skills/yc-intent-radar-skill/yc-jobs-scraper/SKILL.md +59 -0
- package/skills/yc-intent-radar-skill/yc-jobs-scraper/scripts/auth.js +29 -0
- package/skills/yc-intent-radar-skill/yc-jobs-scraper/scripts/db.js +62 -0
- package/skills/yc-intent-radar-skill/yc-jobs-scraper/scripts/export_radar_candidates.js +40 -0
- package/skills/yc-intent-radar-skill/yc-jobs-scraper/scripts/package-lock.json +1525 -0
- package/skills/yc-intent-radar-skill/yc-jobs-scraper/scripts/package.json +12 -0
- package/skills/yc-intent-radar-skill/yc-jobs-scraper/scripts/scraper.js +217 -0
- package/src/e2e.test.ts +35 -0
- package/src/fs-adapters.test.ts +91 -0
- package/src/fs-adapters.ts +65 -0
- package/src/index.ts +182 -0
- package/src/transformers.ts +6 -0
- package/tsconfig.json +8 -0
|
@@ -0,0 +1,556 @@
|
|
|
1
|
+
# Output Templates
|
|
2
|
+
|
|
3
|
+
One template per schema type. Replace every [BRACKETED_FIELD] with content extracted from the page. Never leave bracket text in the final output. If a required field is not found on the page, write `"MISSING_fieldName": "not found on page"` instead of guessing.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Template: FAQPage
|
|
8
|
+
|
|
9
|
+
```json
|
|
10
|
+
{
|
|
11
|
+
"@context": "https://schema.org",
|
|
12
|
+
"@type": "FAQPage",
|
|
13
|
+
"mainEntity": [
|
|
14
|
+
{
|
|
15
|
+
"@type": "Question",
|
|
16
|
+
"name": "[QUESTION_TEXT_1]",
|
|
17
|
+
"acceptedAnswer": {
|
|
18
|
+
"@type": "Answer",
|
|
19
|
+
"text": "[ANSWER_TEXT_1]"
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"@type": "Question",
|
|
24
|
+
"name": "[QUESTION_TEXT_2]",
|
|
25
|
+
"acceptedAnswer": {
|
|
26
|
+
"@type": "Answer",
|
|
27
|
+
"text": "[ANSWER_TEXT_2]"
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
]
|
|
31
|
+
}
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Add more Question objects for each FAQ pair on the page. Minimum 2.
|
|
35
|
+
|
|
36
|
+
Worked example:
|
|
37
|
+
|
|
38
|
+
```json
|
|
39
|
+
{
|
|
40
|
+
"@context": "https://schema.org",
|
|
41
|
+
"@type": "FAQPage",
|
|
42
|
+
"mainEntity": [
|
|
43
|
+
{
|
|
44
|
+
"@type": "Question",
|
|
45
|
+
"name": "How long does shipping take?",
|
|
46
|
+
"acceptedAnswer": {
|
|
47
|
+
"@type": "Answer",
|
|
48
|
+
"text": "Standard shipping takes 5-7 business days. Express shipping takes 1-2 business days."
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
"@type": "Question",
|
|
53
|
+
"name": "Do you offer refunds?",
|
|
54
|
+
"acceptedAnswer": {
|
|
55
|
+
"@type": "Answer",
|
|
56
|
+
"text": "Yes. We offer full refunds within 30 days of purchase. Contact support@example.com to start a return."
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
]
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## Template: Article / BlogPosting
|
|
66
|
+
|
|
67
|
+
```json
|
|
68
|
+
{
|
|
69
|
+
"@context": "https://schema.org",
|
|
70
|
+
"@type": "BlogPosting",
|
|
71
|
+
"headline": "[ARTICLE_TITLE]",
|
|
72
|
+
"image": [
|
|
73
|
+
"[ARTICLE_IMAGE_URL_16x9]"
|
|
74
|
+
],
|
|
75
|
+
"datePublished": "[PUBLISH_DATE_ISO8601]",
|
|
76
|
+
"dateModified": "[MODIFIED_DATE_ISO8601]",
|
|
77
|
+
"author": {
|
|
78
|
+
"@type": "Person",
|
|
79
|
+
"name": "[AUTHOR_NAME]",
|
|
80
|
+
"url": "[AUTHOR_PROFILE_URL]"
|
|
81
|
+
},
|
|
82
|
+
"publisher": {
|
|
83
|
+
"@type": "Organization",
|
|
84
|
+
"name": "[SITE_NAME]",
|
|
85
|
+
"url": "[SITE_URL]",
|
|
86
|
+
"logo": {
|
|
87
|
+
"@type": "ImageObject",
|
|
88
|
+
"url": "[LOGO_URL]"
|
|
89
|
+
}
|
|
90
|
+
},
|
|
91
|
+
"description": "[ARTICLE_DESCRIPTION]",
|
|
92
|
+
"url": "[ARTICLE_CANONICAL_URL]"
|
|
93
|
+
}
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
Use `"Article"` for general editorial content. Use `"BlogPosting"` for informal blog posts. Use `"NewsArticle"` for news publications.
|
|
97
|
+
|
|
98
|
+
If `dateModified` is not on the page, omit it. If author profile URL is not on the page, use just `"name"` without `"url"`.
|
|
99
|
+
|
|
100
|
+
Worked example:
|
|
101
|
+
|
|
102
|
+
```json
|
|
103
|
+
{
|
|
104
|
+
"@context": "https://schema.org",
|
|
105
|
+
"@type": "BlogPosting",
|
|
106
|
+
"headline": "How We Cut Our API Response Time by 60%",
|
|
107
|
+
"image": [
|
|
108
|
+
"https://blog.example.com/images/api-performance-16x9.jpg"
|
|
109
|
+
],
|
|
110
|
+
"datePublished": "2026-03-15T09:00:00+00:00",
|
|
111
|
+
"dateModified": "2026-03-18T14:30:00+00:00",
|
|
112
|
+
"author": {
|
|
113
|
+
"@type": "Person",
|
|
114
|
+
"name": "Sarah Chen",
|
|
115
|
+
"url": "https://blog.example.com/authors/sarah-chen"
|
|
116
|
+
},
|
|
117
|
+
"publisher": {
|
|
118
|
+
"@type": "Organization",
|
|
119
|
+
"name": "Example Engineering Blog",
|
|
120
|
+
"url": "https://blog.example.com",
|
|
121
|
+
"logo": {
|
|
122
|
+
"@type": "ImageObject",
|
|
123
|
+
"url": "https://blog.example.com/logo.png"
|
|
124
|
+
}
|
|
125
|
+
},
|
|
126
|
+
"description": "We profiled our API and found three changes that reduced p95 latency from 800ms to 320ms.",
|
|
127
|
+
"url": "https://blog.example.com/posts/api-performance"
|
|
128
|
+
}
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
## Template: Organization
|
|
134
|
+
|
|
135
|
+
```json
|
|
136
|
+
{
|
|
137
|
+
"@context": "https://schema.org",
|
|
138
|
+
"@type": "Organization",
|
|
139
|
+
"@id": "[SITE_URL]/#organization",
|
|
140
|
+
"name": "[COMPANY_NAME]",
|
|
141
|
+
"url": "[COMPANY_URL]",
|
|
142
|
+
"logo": {
|
|
143
|
+
"@type": "ImageObject",
|
|
144
|
+
"url": "[LOGO_URL]",
|
|
145
|
+
"width": [LOGO_WIDTH],
|
|
146
|
+
"height": [LOGO_HEIGHT]
|
|
147
|
+
},
|
|
148
|
+
"description": "[COMPANY_DESCRIPTION]",
|
|
149
|
+
"sameAs": [
|
|
150
|
+
"[SOCIAL_PROFILE_URL_1]",
|
|
151
|
+
"[SOCIAL_PROFILE_URL_2]"
|
|
152
|
+
],
|
|
153
|
+
"contactPoint": {
|
|
154
|
+
"@type": "ContactPoint",
|
|
155
|
+
"contactType": "customer support",
|
|
156
|
+
"email": "[SUPPORT_EMAIL]"
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
Include only social profiles and contact info that appear on the page. Omit `contactPoint` if no contact details are visible. Omit `logo` dimensions if not known.
|
|
162
|
+
|
|
163
|
+
Worked example:
|
|
164
|
+
|
|
165
|
+
```json
|
|
166
|
+
{
|
|
167
|
+
"@context": "https://schema.org",
|
|
168
|
+
"@type": "Organization",
|
|
169
|
+
"@id": "https://example.com/#organization",
|
|
170
|
+
"name": "Acme Corp",
|
|
171
|
+
"url": "https://example.com",
|
|
172
|
+
"logo": {
|
|
173
|
+
"@type": "ImageObject",
|
|
174
|
+
"url": "https://example.com/logo.png"
|
|
175
|
+
},
|
|
176
|
+
"description": "Acme Corp builds developer tools for API monitoring and observability.",
|
|
177
|
+
"sameAs": [
|
|
178
|
+
"https://www.linkedin.com/company/acme-corp",
|
|
179
|
+
"https://github.com/acme-corp",
|
|
180
|
+
"https://twitter.com/acmecorp"
|
|
181
|
+
],
|
|
182
|
+
"contactPoint": {
|
|
183
|
+
"@type": "ContactPoint",
|
|
184
|
+
"contactType": "customer support",
|
|
185
|
+
"email": "support@example.com"
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
---
|
|
191
|
+
|
|
192
|
+
## Template: Product
|
|
193
|
+
|
|
194
|
+
```json
|
|
195
|
+
{
|
|
196
|
+
"@context": "https://schema.org",
|
|
197
|
+
"@type": "Product",
|
|
198
|
+
"name": "[PRODUCT_NAME]",
|
|
199
|
+
"image": [
|
|
200
|
+
"[PRODUCT_IMAGE_URL]"
|
|
201
|
+
],
|
|
202
|
+
"description": "[PRODUCT_DESCRIPTION]",
|
|
203
|
+
"brand": {
|
|
204
|
+
"@type": "Brand",
|
|
205
|
+
"name": "[BRAND_NAME]"
|
|
206
|
+
},
|
|
207
|
+
"offers": {
|
|
208
|
+
"@type": "Offer",
|
|
209
|
+
"url": "[PRODUCT_PAGE_URL]",
|
|
210
|
+
"priceCurrency": "[CURRENCY_CODE]",
|
|
211
|
+
"price": "[PRICE_VALUE]",
|
|
212
|
+
"availability": "https://schema.org/InStock"
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
For availability, use one of:
|
|
218
|
+
- `"https://schema.org/InStock"` — product is available
|
|
219
|
+
- `"https://schema.org/OutOfStock"` — product is not available
|
|
220
|
+
- `"https://schema.org/PreOrder"` — product is available for pre-order
|
|
221
|
+
|
|
222
|
+
Add `aggregateRating` only if actual ratings and review counts are visible on the page.
|
|
223
|
+
|
|
224
|
+
Worked example:
|
|
225
|
+
|
|
226
|
+
```json
|
|
227
|
+
{
|
|
228
|
+
"@context": "https://schema.org",
|
|
229
|
+
"@type": "Product",
|
|
230
|
+
"name": "API Monitor Pro",
|
|
231
|
+
"image": [
|
|
232
|
+
"https://example.com/product/api-monitor-16x9.jpg",
|
|
233
|
+
"https://example.com/product/api-monitor-1x1.jpg"
|
|
234
|
+
],
|
|
235
|
+
"description": "Real-time API monitoring with alerting, dashboards, and 90-day log retention.",
|
|
236
|
+
"brand": {
|
|
237
|
+
"@type": "Brand",
|
|
238
|
+
"name": "Acme Corp"
|
|
239
|
+
},
|
|
240
|
+
"offers": {
|
|
241
|
+
"@type": "Offer",
|
|
242
|
+
"url": "https://example.com/products/api-monitor-pro",
|
|
243
|
+
"priceCurrency": "USD",
|
|
244
|
+
"price": "49.00",
|
|
245
|
+
"availability": "https://schema.org/InStock"
|
|
246
|
+
},
|
|
247
|
+
"aggregateRating": {
|
|
248
|
+
"@type": "AggregateRating",
|
|
249
|
+
"ratingValue": 4.7,
|
|
250
|
+
"reviewCount": 128,
|
|
251
|
+
"bestRating": 5
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
---
|
|
257
|
+
|
|
258
|
+
## Template: WebSite
|
|
259
|
+
|
|
260
|
+
```json
|
|
261
|
+
{
|
|
262
|
+
"@context": "https://schema.org",
|
|
263
|
+
"@type": "WebSite",
|
|
264
|
+
"@id": "[SITE_URL]/#website",
|
|
265
|
+
"name": "[SITE_NAME]",
|
|
266
|
+
"url": "[SITE_URL]",
|
|
267
|
+
"potentialAction": {
|
|
268
|
+
"@type": "SearchAction",
|
|
269
|
+
"target": {
|
|
270
|
+
"@type": "EntryPoint",
|
|
271
|
+
"urlTemplate": "[SEARCH_URL_TEMPLATE]"
|
|
272
|
+
},
|
|
273
|
+
"query-input": "required name=search_term_string"
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
Only include `potentialAction` if the site has a working search feature. For sites without search, use the minimal version:
|
|
279
|
+
|
|
280
|
+
```json
|
|
281
|
+
{
|
|
282
|
+
"@context": "https://schema.org",
|
|
283
|
+
"@type": "WebSite",
|
|
284
|
+
"@id": "[SITE_URL]/#website",
|
|
285
|
+
"name": "[SITE_NAME]",
|
|
286
|
+
"url": "[SITE_URL]"
|
|
287
|
+
}
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
Worked example (with search):
|
|
291
|
+
|
|
292
|
+
```json
|
|
293
|
+
{
|
|
294
|
+
"@context": "https://schema.org",
|
|
295
|
+
"@type": "WebSite",
|
|
296
|
+
"@id": "https://example.com/#website",
|
|
297
|
+
"name": "Example",
|
|
298
|
+
"url": "https://example.com",
|
|
299
|
+
"potentialAction": {
|
|
300
|
+
"@type": "SearchAction",
|
|
301
|
+
"target": {
|
|
302
|
+
"@type": "EntryPoint",
|
|
303
|
+
"urlTemplate": "https://example.com/search?q={search_term_string}"
|
|
304
|
+
},
|
|
305
|
+
"query-input": "required name=search_term_string"
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
---
|
|
311
|
+
|
|
312
|
+
## Template: HowTo
|
|
313
|
+
|
|
314
|
+
```json
|
|
315
|
+
{
|
|
316
|
+
"@context": "https://schema.org",
|
|
317
|
+
"@type": "HowTo",
|
|
318
|
+
"name": "[GUIDE_TITLE]",
|
|
319
|
+
"image": "[GUIDE_FEATURE_IMAGE_URL]",
|
|
320
|
+
"estimatedDuration": "[DURATION_ISO8601]",
|
|
321
|
+
"step": [
|
|
322
|
+
{
|
|
323
|
+
"@type": "HowToStep",
|
|
324
|
+
"name": "[STEP_1_TITLE]",
|
|
325
|
+
"text": "[STEP_1_DESCRIPTION]"
|
|
326
|
+
},
|
|
327
|
+
{
|
|
328
|
+
"@type": "HowToStep",
|
|
329
|
+
"name": "[STEP_2_TITLE]",
|
|
330
|
+
"text": "[STEP_2_DESCRIPTION]"
|
|
331
|
+
}
|
|
332
|
+
]
|
|
333
|
+
}
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
Omit `image` if there is no feature image on the page. Omit `estimatedDuration` if no time estimate is given. Add one HowToStep object for each numbered step on the page.
|
|
337
|
+
|
|
338
|
+
Worked example:
|
|
339
|
+
|
|
340
|
+
```json
|
|
341
|
+
{
|
|
342
|
+
"@context": "https://schema.org",
|
|
343
|
+
"@type": "HowTo",
|
|
344
|
+
"name": "How to Set Up SSH Key Authentication",
|
|
345
|
+
"estimatedDuration": "PT10M",
|
|
346
|
+
"step": [
|
|
347
|
+
{
|
|
348
|
+
"@type": "HowToStep",
|
|
349
|
+
"name": "Generate an SSH key pair",
|
|
350
|
+
"text": "Run ssh-keygen -t ed25519 -C your-email@example.com and follow the prompts."
|
|
351
|
+
},
|
|
352
|
+
{
|
|
353
|
+
"@type": "HowToStep",
|
|
354
|
+
"name": "Copy your public key to the server",
|
|
355
|
+
"text": "Run ssh-copy-id user@server-address to add your public key to the server's authorized_keys file."
|
|
356
|
+
},
|
|
357
|
+
{
|
|
358
|
+
"@type": "HowToStep",
|
|
359
|
+
"name": "Test the connection",
|
|
360
|
+
"text": "Run ssh user@server-address. You should connect without a password prompt."
|
|
361
|
+
}
|
|
362
|
+
]
|
|
363
|
+
}
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
---
|
|
367
|
+
|
|
368
|
+
## Template: BreadcrumbList
|
|
369
|
+
|
|
370
|
+
```json
|
|
371
|
+
{
|
|
372
|
+
"@context": "https://schema.org",
|
|
373
|
+
"@type": "BreadcrumbList",
|
|
374
|
+
"itemListElement": [
|
|
375
|
+
{
|
|
376
|
+
"@type": "ListItem",
|
|
377
|
+
"position": 1,
|
|
378
|
+
"name": "[BREADCRUMB_1_TEXT]",
|
|
379
|
+
"item": "[BREADCRUMB_1_URL]"
|
|
380
|
+
},
|
|
381
|
+
{
|
|
382
|
+
"@type": "ListItem",
|
|
383
|
+
"position": 2,
|
|
384
|
+
"name": "[BREADCRUMB_2_TEXT]",
|
|
385
|
+
"item": "[BREADCRUMB_2_URL]"
|
|
386
|
+
},
|
|
387
|
+
{
|
|
388
|
+
"@type": "ListItem",
|
|
389
|
+
"position": 3,
|
|
390
|
+
"name": "[CURRENT_PAGE_TITLE]"
|
|
391
|
+
}
|
|
392
|
+
]
|
|
393
|
+
}
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
The last item in the list is the current page. It does not need an `item` URL. All other items need absolute URLs.
|
|
397
|
+
|
|
398
|
+
Worked example:
|
|
399
|
+
|
|
400
|
+
```json
|
|
401
|
+
{
|
|
402
|
+
"@context": "https://schema.org",
|
|
403
|
+
"@type": "BreadcrumbList",
|
|
404
|
+
"itemListElement": [
|
|
405
|
+
{
|
|
406
|
+
"@type": "ListItem",
|
|
407
|
+
"position": 1,
|
|
408
|
+
"name": "Home",
|
|
409
|
+
"item": "https://example.com"
|
|
410
|
+
},
|
|
411
|
+
{
|
|
412
|
+
"@type": "ListItem",
|
|
413
|
+
"position": 2,
|
|
414
|
+
"name": "Blog",
|
|
415
|
+
"item": "https://example.com/blog"
|
|
416
|
+
},
|
|
417
|
+
{
|
|
418
|
+
"@type": "ListItem",
|
|
419
|
+
"position": 3,
|
|
420
|
+
"name": "How to Set Up SSH Key Authentication"
|
|
421
|
+
}
|
|
422
|
+
]
|
|
423
|
+
}
|
|
424
|
+
```
|
|
425
|
+
|
|
426
|
+
---
|
|
427
|
+
|
|
428
|
+
## Template: SoftwareApplication
|
|
429
|
+
|
|
430
|
+
```json
|
|
431
|
+
{
|
|
432
|
+
"@context": "https://schema.org",
|
|
433
|
+
"@type": "SoftwareApplication",
|
|
434
|
+
"name": "[APP_NAME]",
|
|
435
|
+
"operatingSystem": "[OS]",
|
|
436
|
+
"applicationCategory": "[CATEGORY]",
|
|
437
|
+
"description": "[APP_DESCRIPTION]",
|
|
438
|
+
"url": "[APP_URL]",
|
|
439
|
+
"offers": {
|
|
440
|
+
"@type": "Offer",
|
|
441
|
+
"price": "[PRICE]",
|
|
442
|
+
"priceCurrency": "[CURRENCY_CODE]"
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
```
|
|
446
|
+
|
|
447
|
+
For free apps, use `"price": "0"`. For `applicationCategory`, use one of: `"GameApplication"`, `"BusinessApplication"`, `"EducationalApplication"`, `"DeveloperApplication"`, `"DesignApplication"`, `"UtilitiesApplication"`, `"SecurityApplication"`.
|
|
448
|
+
|
|
449
|
+
For `operatingSystem`, use: `"Windows"`, `"macOS"`, `"Linux"`, `"Android"`, `"iOS"`, `"Web"`. Use an array if multiple apply: `["macOS", "Windows", "Linux"]`.
|
|
450
|
+
|
|
451
|
+
Worked example:
|
|
452
|
+
|
|
453
|
+
```json
|
|
454
|
+
{
|
|
455
|
+
"@context": "https://schema.org",
|
|
456
|
+
"@type": "SoftwareApplication",
|
|
457
|
+
"name": "API Monitor Pro",
|
|
458
|
+
"operatingSystem": "Web",
|
|
459
|
+
"applicationCategory": "DeveloperApplication",
|
|
460
|
+
"description": "Real-time API monitoring with alerting and 90-day log retention.",
|
|
461
|
+
"url": "https://example.com/products/api-monitor-pro",
|
|
462
|
+
"offers": {
|
|
463
|
+
"@type": "Offer",
|
|
464
|
+
"price": "49.00",
|
|
465
|
+
"priceCurrency": "USD"
|
|
466
|
+
},
|
|
467
|
+
"aggregateRating": {
|
|
468
|
+
"@type": "AggregateRating",
|
|
469
|
+
"ratingValue": 4.7,
|
|
470
|
+
"reviewCount": 128,
|
|
471
|
+
"bestRating": 5
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
```
|
|
475
|
+
|
|
476
|
+
---
|
|
477
|
+
|
|
478
|
+
## Template: LocalBusiness
|
|
479
|
+
|
|
480
|
+
```json
|
|
481
|
+
{
|
|
482
|
+
"@context": "https://schema.org",
|
|
483
|
+
"@type": "LocalBusiness",
|
|
484
|
+
"name": "[BUSINESS_NAME]",
|
|
485
|
+
"address": {
|
|
486
|
+
"@type": "PostalAddress",
|
|
487
|
+
"streetAddress": "[STREET_ADDRESS]",
|
|
488
|
+
"addressLocality": "[CITY]",
|
|
489
|
+
"addressRegion": "[STATE_OR_REGION]",
|
|
490
|
+
"postalCode": "[POSTAL_CODE]",
|
|
491
|
+
"addressCountry": "[COUNTRY_CODE]"
|
|
492
|
+
},
|
|
493
|
+
"telephone": "[PHONE_NUMBER]",
|
|
494
|
+
"url": "[WEBSITE_URL]",
|
|
495
|
+
"openingHoursSpecification": [
|
|
496
|
+
{
|
|
497
|
+
"@type": "OpeningHoursSpecification",
|
|
498
|
+
"dayOfWeek": ["[DAY_1]", "[DAY_2]"],
|
|
499
|
+
"opens": "[OPENS_TIME]",
|
|
500
|
+
"closes": "[CLOSES_TIME]"
|
|
501
|
+
}
|
|
502
|
+
]
|
|
503
|
+
}
|
|
504
|
+
```
|
|
505
|
+
|
|
506
|
+
For `addressCountry`, use ISO 3166-1 alpha-2 codes: "US", "GB", "CA", "AU", etc.
|
|
507
|
+
|
|
508
|
+
For `dayOfWeek`, use full day names: "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday".
|
|
509
|
+
|
|
510
|
+
For opening hours times, use 24-hour format: "09:00", "17:30", "22:00".
|
|
511
|
+
|
|
512
|
+
Worked example:
|
|
513
|
+
|
|
514
|
+
```json
|
|
515
|
+
{
|
|
516
|
+
"@context": "https://schema.org",
|
|
517
|
+
"@type": "LocalBusiness",
|
|
518
|
+
"name": "Riverside Coffee",
|
|
519
|
+
"address": {
|
|
520
|
+
"@type": "PostalAddress",
|
|
521
|
+
"streetAddress": "42 Market Street",
|
|
522
|
+
"addressLocality": "Portland",
|
|
523
|
+
"addressRegion": "OR",
|
|
524
|
+
"postalCode": "97201",
|
|
525
|
+
"addressCountry": "US"
|
|
526
|
+
},
|
|
527
|
+
"telephone": "+1-503-555-0142",
|
|
528
|
+
"url": "https://riversidecoffee.example.com",
|
|
529
|
+
"openingHoursSpecification": [
|
|
530
|
+
{
|
|
531
|
+
"@type": "OpeningHoursSpecification",
|
|
532
|
+
"dayOfWeek": ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"],
|
|
533
|
+
"opens": "07:00",
|
|
534
|
+
"closes": "18:00"
|
|
535
|
+
},
|
|
536
|
+
{
|
|
537
|
+
"@type": "OpeningHoursSpecification",
|
|
538
|
+
"dayOfWeek": ["Saturday", "Sunday"],
|
|
539
|
+
"opens": "08:00",
|
|
540
|
+
"closes": "16:00"
|
|
541
|
+
}
|
|
542
|
+
]
|
|
543
|
+
}
|
|
544
|
+
```
|
|
545
|
+
|
|
546
|
+
---
|
|
547
|
+
|
|
548
|
+
## Fill-in Rules
|
|
549
|
+
|
|
550
|
+
1. Replace every [BRACKETED_FIELD] with content from the page. Never use the bracket text in the final output.
|
|
551
|
+
2. If a required field is not on the page, write: `"MISSING_fieldName": "not found on page"`
|
|
552
|
+
3. If a recommended field is not on the page, omit it silently.
|
|
553
|
+
4. All URLs must be absolute (start with `https://`).
|
|
554
|
+
5. All dates must be ISO 8601 format.
|
|
555
|
+
6. Validate JSON syntax: no trailing commas, balanced brackets, all strings in double quotes.
|
|
556
|
+
7. Output each schema type as a separate `<script type="application/ld+json">` block.
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# show-hn-writer — Environment Variables
|
|
2
|
+
# =========================================
|
|
3
|
+
# All variables are optional. The skill runs in output-only mode without any of them.
|
|
4
|
+
|
|
5
|
+
# Optional: Google Gemini API key for automated draft quality review
|
|
6
|
+
# Without this: the skill runs the manual self-QA checklist instead
|
|
7
|
+
# Get it: aistudio.google.com, Get API key
|
|
8
|
+
GEMINI_API_KEY=your_gemini_api_key_here
|
|
9
|
+
|
|
10
|
+
# Optional: Hacker News credentials for direct post submission
|
|
11
|
+
# Without these: the skill outputs the draft for manual copy-paste submission
|
|
12
|
+
# Both must be set to enable direct posting. Never commit this file with real values.
|
|
13
|
+
HN_USERNAME=your_hn_username_here
|
|
14
|
+
HN_PASSWORD=your_hn_password_here
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# show-hn-writer
|
|
2
|
+
|
|
3
|
+
<img width="1280" height="640" alt="show-hn-writer" src="https://github.com/user-attachments/assets/224030e0-c3e0-499c-98d4-a049d7dddc51" />
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
Draft a Show HN post (title + body) that follows Hacker News norms: specific, honest, first-person, no marketing. Generates three title variants and a complete body, then runs a Gemini review to catch HN anti-patterns before you post.
|
|
7
|
+
|
|
8
|
+
## What It Does
|
|
9
|
+
|
|
10
|
+
- Reads your project context (from README or your answers)
|
|
11
|
+
- Drafts three Show HN title variants in different formats
|
|
12
|
+
- Writes a 150-350 word body following HN community norms
|
|
13
|
+
- Uses Gemini to flag marketing language, vague descriptions, or other HN anti-patterns
|
|
14
|
+
- Runs a self-QA checklist before presenting output
|
|
15
|
+
- Includes submission notes (timing, first-comment strategy, resubmission rules)
|
|
16
|
+
|
|
17
|
+
## Requirements
|
|
18
|
+
|
|
19
|
+
| Requirement | Purpose | How to Set Up |
|
|
20
|
+
|------------|---------|--------------|
|
|
21
|
+
| Gemini API key (optional) | Automated draft review for HN anti-patterns | aistudio.google.com, Get API key |
|
|
22
|
+
|
|
23
|
+
The skill works without Gemini: it runs the manual self-QA checklist instead.
|
|
24
|
+
|
|
25
|
+
## Setup
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
cp .env.example .env
|
|
29
|
+
# Add GEMINI_API_KEY if you want automated review (optional)
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## How to Use
|
|
33
|
+
|
|
34
|
+
From a README:
|
|
35
|
+
```
|
|
36
|
+
"Write a Show HN post for my project"
|
|
37
|
+
"Help me launch on Hacker News"
|
|
38
|
+
"Draft a Show HN for the project in this repo"
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
With explicit context:
|
|
42
|
+
```
|
|
43
|
+
"Write a Show HN post for [project name]: [what it does]. I built it because [reason]."
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
For a specific title format:
|
|
47
|
+
```
|
|
48
|
+
"Write a Show HN title for my CLI tool that converts JSON to TypeScript interfaces"
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Show HN Title Formats
|
|
52
|
+
|
|
53
|
+
| Format | Example | Best For |
|
|
54
|
+
|--------|---------|----------|
|
|
55
|
+
| Product-First | `Show HN: Datasette – Instantly publish SQLite databases to the web` | Single-function tools |
|
|
56
|
+
| Outcome-Focused | `Show HN: Jitsi – Group video calls without an account` | Tools replacing something painful |
|
|
57
|
+
| Technical-Angle | `Show HN: Bun – JavaScript runtime built in Zig` | Dev tools where the implementation matters |
|
|
58
|
+
| Experiment | `Show HN: Ink – React for command-line apps` | Projects challenging a convention |
|
|
59
|
+
|
|
60
|
+
## What Makes a Good Show HN Post
|
|
61
|
+
|
|
62
|
+
**Title:** 60-80 characters. Starts with "Show HN:". En dash separator. No adjectives.
|
|
63
|
+
|
|
64
|
+
**Body:** First-person. 150-350 words. At least one technical detail. Honest about limitations. Ends with an invitation for feedback, not a CTA.
|
|
65
|
+
|
|
66
|
+
**What kills HN posts:**
|
|
67
|
+
- Vague titles ("Show HN: I built a thing for developers")
|
|
68
|
+
- Marketing adjectives ("fast", "simple", "powerful")
|
|
69
|
+
- Asking for upvotes
|
|
70
|
+
- Body that reads like a product page
|
|
71
|
+
|
|
72
|
+
## Project Structure
|
|
73
|
+
|
|
74
|
+
```
|
|
75
|
+
show-hn-writer/
|
|
76
|
+
├── SKILL.md
|
|
77
|
+
├── README.md
|
|
78
|
+
├── .env.example
|
|
79
|
+
├── evals/
|
|
80
|
+
│ └── evals.json
|
|
81
|
+
└── references/
|
|
82
|
+
├── hn-rules.md
|
|
83
|
+
└── title-formulas.md
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## License
|
|
87
|
+
|
|
88
|
+
MIT
|