@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.
Files changed (212) hide show
  1. package/.claude/skills/claude-md-generator/.env.example +7 -0
  2. package/.claude/skills/claude-md-generator/README.md +78 -0
  3. package/.claude/skills/claude-md-generator/SKILL.md +248 -0
  4. package/.claude/skills/claude-md-generator/evals/evals.json +35 -0
  5. package/.claude/skills/claude-md-generator/references/section-guide.md +175 -0
  6. package/dist/e2e.test.d.ts +1 -0
  7. package/dist/e2e.test.js +62 -0
  8. package/dist/fs-adapters.d.ts +4 -0
  9. package/dist/fs-adapters.js +101 -0
  10. package/dist/fs-adapters.test.d.ts +1 -0
  11. package/dist/fs-adapters.test.js +108 -0
  12. package/dist/index.d.ts +2 -0
  13. package/dist/index.js +211 -0
  14. package/dist/transformers.d.ts +6 -0
  15. package/dist/transformers.js +2 -0
  16. package/package.json +25 -0
  17. package/registry.json +226 -0
  18. package/skills/blog-cover-image-cli/.github/workflows/publish.yml +19 -0
  19. package/skills/blog-cover-image-cli/LICENSE +15 -0
  20. package/skills/blog-cover-image-cli/README.md +126 -0
  21. package/skills/blog-cover-image-cli/SKILL.md +7 -0
  22. package/skills/blog-cover-image-cli/agent-skill/blog-cover-generator/README.md +30 -0
  23. package/skills/blog-cover-image-cli/agent-skill/blog-cover-generator/SKILL.md +72 -0
  24. package/skills/blog-cover-image-cli/bin/cli.js +226 -0
  25. package/skills/blog-cover-image-cli/examples/100x_UX_Research_AI_Agent.png +0 -0
  26. package/skills/blog-cover-image-cli/examples/Firecrawl-supabase-bolt.png +0 -0
  27. package/skills/blog-cover-image-cli/examples/Git-City_Case_study_Cover_Image.jpg +0 -0
  28. package/skills/blog-cover-image-cli/examples/THE DISTRIBUTION LAYER (2).png +0 -0
  29. package/skills/blog-cover-image-cli/examples/canva-perplexity-duolingo-cover-image.png +0 -0
  30. package/skills/blog-cover-image-cli/examples/gamma-mistral-veed.png +0 -0
  31. package/skills/blog-cover-image-cli/examples/server-survival-case-study-cover-image(1).png +0 -0
  32. package/skills/blog-cover-image-cli/examples/viral-meme-automation.png +0 -0
  33. package/skills/blog-cover-image-cli/index.js +2 -0
  34. package/skills/blog-cover-image-cli/package-lock.json +2238 -0
  35. package/skills/blog-cover-image-cli/package.json +37 -0
  36. package/skills/blog-cover-image-cli/src/geminiGenerator.js +126 -0
  37. package/skills/blog-cover-image-cli/src/imageValidator.js +54 -0
  38. package/skills/blog-cover-image-cli/src/logoFetcher.js +86 -0
  39. package/skills/claude-md-generator/.env.example +7 -0
  40. package/skills/claude-md-generator/README.md +78 -0
  41. package/skills/claude-md-generator/SKILL.md +254 -0
  42. package/skills/claude-md-generator/evals/evals.json +35 -0
  43. package/skills/claude-md-generator/references/section-guide.md +175 -0
  44. package/skills/cook-the-blog/README.md +86 -0
  45. package/skills/cook-the-blog/SKILL.md +130 -0
  46. package/skills/dependency-update-bot/.env.example +13 -0
  47. package/skills/dependency-update-bot/README.md +101 -0
  48. package/skills/dependency-update-bot/SKILL.md +376 -0
  49. package/skills/dependency-update-bot/evals/evals.json +45 -0
  50. package/skills/dependency-update-bot/references/changelog-patterns.md +201 -0
  51. package/skills/docs-from-code/.env.example +13 -0
  52. package/skills/docs-from-code/README.md +97 -0
  53. package/skills/docs-from-code/SKILL.md +160 -0
  54. package/skills/docs-from-code/evals/evals.json +29 -0
  55. package/skills/docs-from-code/references/extraction-guide.md +174 -0
  56. package/skills/docs-from-code/references/output-template.md +135 -0
  57. package/skills/docs-from-code/scripts/extract_py.py +238 -0
  58. package/skills/docs-from-code/scripts/extract_ts.ts +284 -0
  59. package/skills/docs-from-code/scripts/package.json +18 -0
  60. package/skills/explain-this-pr/README.md +74 -0
  61. package/skills/explain-this-pr/SKILL.md +130 -0
  62. package/skills/explain-this-pr/evals/evals.json +35 -0
  63. package/skills/google-trends-api-skills/README.md +78 -0
  64. package/skills/google-trends-api-skills/SKILL.md +7 -0
  65. package/skills/google-trends-api-skills/google-trends-api/SKILL.md +163 -0
  66. package/skills/google-trends-api-skills/google-trends-api/references/api-responses.md +188 -0
  67. package/skills/google-trends-api-skills/google-trends-api/scripts/discover_keywords.py +344 -0
  68. package/skills/google-trends-api-skills/seo-keyword-research/SKILL.md +205 -0
  69. package/skills/google-trends-api-skills/seo-keyword-research/references/keyword-placement-guide.md +89 -0
  70. package/skills/google-trends-api-skills/seo-keyword-research/references/tech-blog-examples.md +207 -0
  71. package/skills/google-trends-api-skills/seo-keyword-research/scripts/blog_seo_research.py +373 -0
  72. package/skills/hackernews-intel/.env.example +33 -0
  73. package/skills/hackernews-intel/README.md +161 -0
  74. package/skills/hackernews-intel/SKILL.md +156 -0
  75. package/skills/hackernews-intel/evals/evals.json +35 -0
  76. package/skills/hackernews-intel/package.json +15 -0
  77. package/skills/hackernews-intel/scripts/monitor-hn.js +258 -0
  78. package/skills/kill-the-standup/.env.example +22 -0
  79. package/skills/kill-the-standup/README.md +84 -0
  80. package/skills/kill-the-standup/SKILL.md +169 -0
  81. package/skills/kill-the-standup/evals/evals.json +35 -0
  82. package/skills/kill-the-standup/references/standup-format.md +102 -0
  83. package/skills/linkedin-post-generator/.env.example +14 -0
  84. package/skills/linkedin-post-generator/README.md +107 -0
  85. package/skills/linkedin-post-generator/SKILL.md +228 -0
  86. package/skills/linkedin-post-generator/evals/evals.json +35 -0
  87. package/skills/linkedin-post-generator/references/linkedin-format.md +216 -0
  88. package/skills/linkedin-post-generator/references/output-template.md +154 -0
  89. package/skills/llms-txt-generator/.env.example +18 -0
  90. package/skills/llms-txt-generator/README.md +142 -0
  91. package/skills/llms-txt-generator/SKILL.md +176 -0
  92. package/skills/llms-txt-generator/evals/evals.json +35 -0
  93. package/skills/llms-txt-generator/references/llms-txt-spec.md +88 -0
  94. package/skills/llms-txt-generator/references/output-template.md +76 -0
  95. package/skills/llms-txt-generator/test-output/genzcareer.in/llms.txt +31 -0
  96. package/skills/luma-attendees-scraper/README.md +170 -0
  97. package/skills/luma-attendees-scraper/SKILL.md +7 -0
  98. package/skills/luma-attendees-scraper/luma_attendees_export.js +223 -0
  99. package/skills/meeting-brief-generator/.env.example +21 -0
  100. package/skills/meeting-brief-generator/README.md +90 -0
  101. package/skills/meeting-brief-generator/SKILL.md +275 -0
  102. package/skills/meeting-brief-generator/evals/evals.json +35 -0
  103. package/skills/meeting-brief-generator/references/brief-format.md +114 -0
  104. package/skills/meeting-brief-generator/references/output-template.md +150 -0
  105. package/skills/meta-ads-skill/README.md +100 -0
  106. package/skills/meta-ads-skill/SKILL.md +7 -0
  107. package/skills/meta-ads-skill/meta-ads-skill/SKILL.md +41 -0
  108. package/skills/meta-ads-skill/meta-ads-skill/references/report_templates.md +47 -0
  109. package/skills/meta-ads-skill/meta-ads-skill/references/workflows.md +51 -0
  110. package/skills/meta-ads-skill/meta-ads-skill/scripts/auth_check.py +22 -0
  111. package/skills/meta-ads-skill/meta-ads-skill/scripts/formatters.py +46 -0
  112. package/skills/newsletter-digest/.env.example +20 -0
  113. package/skills/newsletter-digest/README.md +147 -0
  114. package/skills/newsletter-digest/SKILL.md +221 -0
  115. package/skills/newsletter-digest/evals/evals.json +35 -0
  116. package/skills/newsletter-digest/feeds.json +7 -0
  117. package/skills/newsletter-digest/package.json +15 -0
  118. package/skills/newsletter-digest/references/digest-format.md +123 -0
  119. package/skills/newsletter-digest/references/output-template.md +136 -0
  120. package/skills/newsletter-digest/scripts/fetch-feeds.js +141 -0
  121. package/skills/newsletter-digest/scripts/ghost-publish.js +147 -0
  122. package/skills/noise2blog/.env.example +16 -0
  123. package/skills/noise2blog/README.md +107 -0
  124. package/skills/noise2blog/SKILL.md +229 -0
  125. package/skills/noise2blog/evals/evals.json +35 -0
  126. package/skills/noise2blog/references/blog-format.md +188 -0
  127. package/skills/noise2blog/references/output-template.md +184 -0
  128. package/skills/outreach-sequence-builder/.env.example +12 -0
  129. package/skills/outreach-sequence-builder/README.md +108 -0
  130. package/skills/outreach-sequence-builder/SKILL.md +248 -0
  131. package/skills/outreach-sequence-builder/evals/evals.json +36 -0
  132. package/skills/outreach-sequence-builder/references/output-template.md +171 -0
  133. package/skills/outreach-sequence-builder/references/sequence-format.md +167 -0
  134. package/skills/outreach-sequence-builder/references/signal-playbook.md +117 -0
  135. package/skills/position-me/README.md +71 -0
  136. package/skills/position-me/SKILL.md +7 -0
  137. package/skills/position-me/position-me/SKILL.md +50 -0
  138. package/skills/position-me/position-me/references/EVALUATION_SOP.md +40 -0
  139. package/skills/position-me/position-me/references/REPORT_TEMPLATE.md +58 -0
  140. package/skills/position-me/position-me/scripts/extract_links.py +49 -0
  141. package/skills/pr-description-writer/README.md +81 -0
  142. package/skills/pr-description-writer/SKILL.md +141 -0
  143. package/skills/pr-description-writer/evals/evals.json +35 -0
  144. package/skills/pr-description-writer/references/pr-format-guide.md +145 -0
  145. package/skills/producthunt-launch-kit/.env.example +7 -0
  146. package/skills/producthunt-launch-kit/README.md +95 -0
  147. package/skills/producthunt-launch-kit/SKILL.md +380 -0
  148. package/skills/producthunt-launch-kit/evals/evals.json +35 -0
  149. package/skills/producthunt-launch-kit/references/copy-rules.md +124 -0
  150. package/skills/reddit-icp-monitor/.env.example +16 -0
  151. package/skills/reddit-icp-monitor/README.md +117 -0
  152. package/skills/reddit-icp-monitor/SKILL.md +271 -0
  153. package/skills/reddit-icp-monitor/evals/evals.json +40 -0
  154. package/skills/reddit-icp-monitor/references/icp-format.md +131 -0
  155. package/skills/reddit-icp-monitor/references/reply-rules.md +110 -0
  156. package/skills/reddit-post-engine/.env.example +13 -0
  157. package/skills/reddit-post-engine/README.md +103 -0
  158. package/skills/reddit-post-engine/SKILL.md +303 -0
  159. package/skills/reddit-post-engine/evals/evals.json +35 -0
  160. package/skills/reddit-post-engine/references/subreddit-playbook.md +156 -0
  161. package/skills/schema-markup-generator/.env.example +19 -0
  162. package/skills/schema-markup-generator/README.md +114 -0
  163. package/skills/schema-markup-generator/SKILL.md +192 -0
  164. package/skills/schema-markup-generator/evals/evals.json +35 -0
  165. package/skills/schema-markup-generator/references/json-ld-spec.md +263 -0
  166. package/skills/schema-markup-generator/references/output-template.md +556 -0
  167. package/skills/show-hn-writer/.env.example +14 -0
  168. package/skills/show-hn-writer/README.md +88 -0
  169. package/skills/show-hn-writer/SKILL.md +303 -0
  170. package/skills/show-hn-writer/evals/evals.json +35 -0
  171. package/skills/show-hn-writer/references/hn-rules.md +74 -0
  172. package/skills/show-hn-writer/references/title-formulas.md +93 -0
  173. package/skills/stargazer/README.md +79 -0
  174. package/skills/stargazer/SKILL.md +7 -0
  175. package/skills/stargazer/stargazer-skill/SKILL.md +58 -0
  176. package/skills/stargazer/stargazer-skill/assets/.env.example +18 -0
  177. package/skills/stargazer/stargazer-skill/scripts/convert_to_csv.py +63 -0
  178. package/skills/stargazer/stargazer-skill/scripts/count_emails.py +52 -0
  179. package/skills/stargazer/stargazer-skill/scripts/stargazer_deep_extractor.py +450 -0
  180. package/skills/tweet-thread-from-blog/.env.example +14 -0
  181. package/skills/tweet-thread-from-blog/README.md +109 -0
  182. package/skills/tweet-thread-from-blog/SKILL.md +177 -0
  183. package/skills/tweet-thread-from-blog/evals/evals.json +35 -0
  184. package/skills/tweet-thread-from-blog/references/output-template.md +193 -0
  185. package/skills/tweet-thread-from-blog/references/thread-format.md +107 -0
  186. package/skills/twitter-GTM-find-skill/README.md +43 -0
  187. package/skills/twitter-GTM-find-skill/SKILL.md +7 -0
  188. package/skills/twitter-GTM-find-skill/twitter-GTM-find/SKILL.md +37 -0
  189. package/skills/twitter-GTM-find-skill/twitter-GTM-find/references/icp-checklist.md +35 -0
  190. package/skills/twitter-GTM-find-skill/twitter-GTM-find/scripts/package.json +23 -0
  191. package/skills/twitter-GTM-find-skill/twitter-GTM-find/scripts/run_pipeline.sh +8 -0
  192. package/skills/twitter-GTM-find-skill/twitter-GTM-find/scripts/src/debug.ts +23 -0
  193. package/skills/twitter-GTM-find-skill/twitter-GTM-find/scripts/src/extractor.ts +79 -0
  194. package/skills/twitter-GTM-find-skill/twitter-GTM-find/scripts/src/icp-filter.ts +87 -0
  195. package/skills/twitter-GTM-find-skill/twitter-GTM-find/scripts/src/index.ts +94 -0
  196. package/skills/twitter-GTM-find-skill/twitter-GTM-find/scripts/src/scraper.ts +41 -0
  197. package/skills/twitter-GTM-find-skill/twitter-GTM-find/scripts/tsconfig.json +13 -0
  198. package/skills/yc-intent-radar-skill/README.md +39 -0
  199. package/skills/yc-intent-radar-skill/SKILL.md +7 -0
  200. package/skills/yc-intent-radar-skill/yc-jobs-scraper/SKILL.md +59 -0
  201. package/skills/yc-intent-radar-skill/yc-jobs-scraper/scripts/auth.js +29 -0
  202. package/skills/yc-intent-radar-skill/yc-jobs-scraper/scripts/db.js +62 -0
  203. package/skills/yc-intent-radar-skill/yc-jobs-scraper/scripts/export_radar_candidates.js +40 -0
  204. package/skills/yc-intent-radar-skill/yc-jobs-scraper/scripts/package-lock.json +1525 -0
  205. package/skills/yc-intent-radar-skill/yc-jobs-scraper/scripts/package.json +12 -0
  206. package/skills/yc-intent-radar-skill/yc-jobs-scraper/scripts/scraper.js +217 -0
  207. package/src/e2e.test.ts +35 -0
  208. package/src/fs-adapters.test.ts +91 -0
  209. package/src/fs-adapters.ts +65 -0
  210. package/src/index.ts +182 -0
  211. package/src/transformers.ts +6 -0
  212. 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