1---
2name: write-article
3description: Write or edit an SEO/AEO article for the meirlabs web app (apps/web/content/articles). Encodes the frontmatter schema, the answer-engine structure, the "By the numbers" stats convention, and the editorial rules (concrete examples, tiered numbers, plain-language costs, no em dashes, article-specific CTAs). Use when the user says "write an article", "new blog post", "add an article", "edit the cost/timeline article", or wants copy for the /articles section.
4---
5
6# Write Article Skill
7
8How to write and edit articles for the meirlabs site. Articles are Q&A pieces
9built to be quoted by AI answer engines (AEO) and to rank in search (SEO), not
10just read start to finish. Every rule below exists because a real edit was
11needed to fix its absence, keep them.
12
13## General rules vs cost-specific rules
14
15Most of this skill is general and applies to every article: the answer-engine
16structure, the TL;DR/intro split, concrete examples, honest math, tight length,
17sourcing, voice, and the consistency sweep.
18
19A few sections are **cost-specific** and are marked as such: cost tiers, the
20monthly-usage explanation, and promo/discount CTAs. These apply **only** when
21the article is about pricing, ROI, usage fees, or payback. For a timeline,
22operating-model, security, or strategy article, use the same underlying
23principles (concrete, tiered, honest, tight) but do not force cost tiers,
24dollar figures, or a discount pitch where they do not belong. Overfitting every
25article to the cost article is a failure mode, avoid it.
26
27## Where articles live
28
29- One markdown file per article: `apps/web/content/articles/<locale>/<slug>.md`
30- `locale` is one of `en` | `he` | `ru`. Default to `en`; other locales are separate files sharing a `translationKey`.
31- **The filename IS the slug.** `frontmatter.slug` must equal the filename without `.md`, or the build throws.
32- Routes, the sitemap, and hreflang are automatic. Adding a valid file is all it takes to publish, there is no index to register in.
33- The loader/validator is `apps/web/lib/articles.ts`; the renderer (stats icons, CTA, source pills) is `apps/web/app/articles/_components/ArticleView.tsx`. Read those if a field's behavior is unclear.
34
35## Frontmatter (all fields required unless noted)
36
37```yaml
38---
39title: "How Much Does AI Adoption Actually Cost a Small Business?"
40description: "One-sentence meta description. This is the search snippet, make it earn the click."
41slug: "how-much-does-ai-adoption-cost" # MUST match the filename
42translationKey: "ai-adoption-cost" # groups the same article across locales for hreflang
43locale: "en"
44publishedAt: "2026-07-09" # YYYY-MM-DD
45updatedAt: "2026-07-09" # bump when you materially edit
46author: "Meir Rosenschein"
47authorUrl: "https://meirlabs.com/about"
48ogImage: "/logo.png"
49ogImageAlt: "meirlabs logo"
50heroImage: "/articles/how-much-does-ai-adoption-cost/hero.png" # OPTIONAL lead image under the title — most articles omit it (see Images)
51heroImageAlt: "A short description of what the hero image shows" # required ONLY if heroImage is set (build fails otherwise)
52heroCaption: "Optional one-line caption under the hero" # optional
53status: "published" # "draft" | "published" — draft still routes, but is not indexed
54noindex: false
55primaryQuestion: "How much does AI adoption cost for a small business?"
56answerSummary: "…" # the extractable answer — see rules below
57tags: ["ai-adoption", "cost", "getting-started"]
58stats: # optional; omit entirely if there are no numbers worth surfacing
59 - value: "$3k–$5k"
60 label: "To automate one simple task, like drafting routine emails"
61 icon: "wrench"
62sources: # 2–3 real, reputable URLs
63 - title: "Anthropic: Claude API pricing"
64 url: "https://platform.claude.com/docs/en/about-claude/pricing"
65---
66```
67
68`primaryQuestion` doesn't render as visible text — it feeds the FAQPage JSON-LD
69(`apps/web/lib/article-seo.ts`) and must closely match the H1 title in meaning.
70What renders under the H1 is the `answerSummary` TL;DR. Treat both as the most
71important lines in the file.
72
73## The answer-engine structure (non-negotiable shape)
74
751. **Title** — phrase it as, or close to, the question a person types. The "Actually" / "Really" framing tests well. Set `primaryQuestion` to that same question in bare form; it never appears on the page (it only feeds the FAQPage JSON-LD), so it must match the title in meaning.
762. **`answerSummary` (the TL;DR)** — renders under the H1; a self-contained answer an engine can quote without reading the body. See TL;DR rules.
773. **Intro (2–4 sentences)** — do a *different* job than the TL;DR (see the next section). Name and correct the reader's *wrong frame*, set the stakes, or explain why the obvious comparison misleads. e.g. "Most owners price AI like software. Wrong frame."
784. **3–4 H2 headings, each a question**, each answered in one tight paragraph. These are the questions people also ask. Real examples that work:
79 - "What actually costs money in an AI project?"
80 - "Why is the sticker price the wrong thing to compare?"
81 - "Why is the first workflow more expensive than the tenth?"
82 - "What makes AI adoption expensive when it goes wrong?"
835. **A one-line rule/test to close** — "A simple rule to start: …" / "A simple test for the first slice: …". Gives the reader one thing to do.
846. **Optional promo/CTA section** (cost-specific, see CTA rule).
85
86A section that enumerates failure modes or gotchas ("What breaks first?") reads
87as **symptom → fix bullets**, not one dense paragraph — more scannable, and
88each bullet is independently quotable by an answer engine (real edit on the
89WhatsApp article).
90
91**Length: target 600–900 words.** The current articles are strong because they
92are tight. If a draft passes 1,000 words, cut before adding sections. Each H2
93should usually be a single paragraph, not a mini-essay.
94
95## Images & figures
96
97A wall of text does not read like a real publication. Prefer at least one image
98that carries information, not decoration.
99
100- **Bespoke `fig:` figures are the house standard** (every published article
101 ships 1–3). A figure is a hand-designed, theme-aware diagram or chart that
102 carries one of the article's actual arguments — never generic chart filler.
103 Each article's figures live in
104 `apps/web/app/articles/_components/figures/<slug>.tsx`, default-exporting
105 `Record<string, FigureComponent>` (see any existing module for the pattern;
106 `how-much-does-ai-adoption-cost.tsx` is the reference). Embed with
107 ``. An unknown figure name **throws at build
108 time**, so name and module must match.
109- **Figure rules** (from the pilot, keep them): monochrome `--ml-*` tokens only
110 (must read in both themes); labels localized en/he/ru via a LABELS map inside
111 the module; panels forced `dir="ltr"` (figures are LTR islands on the RTL
112 Hebrew pages); every value directly labeled, no hover layer; honest scales
113 (never mix one-time and monthly units on one axis; don't fabricate quantities
114 the prose doesn't claim — a qualitative shape chart drops its y-axis); bars
115 ≤24px with 4px rounded data-ends, 2px surface gaps, hairline gridlines; text
116 in text tokens, never data color; no horizontal scroll at 375px. Shared
117 grammar classes are `.art-fig-*` in `articles.css`; per-figure geometry is
118 inline styles so new figures need no CSS edits.
119- **Design the figure for the argument.** Pick the 2–3 points the article
120 actually argues and give each the form that proves it (range bars, phase
121 timeline, break-even lines, a flow/boundary diagram, a typographic ledger).
122 If the point is qualitative, a diagram beats a chart.
123- **Numbers in figures obey the consistency sweep**: they must match the body,
124 the stats tiles, and any sibling article quoting the same example (the cost
125 and ROI articles share the email-tool math).
126- **Captions do a job.** Say what the reader should take from the image, don't
127 just name it. "Where the $3k–$5k tier lands versus a full software build," not
128 "a chart."
129- **Raster images still work** where a real screenshot/photo is the content:
130 ``. The renderer
131 unwraps a lone-image paragraph into a `<figure>`: the markdown **title** (the
132 quoted part) becomes the visible caption; if omitted, the **alt** is used.
133- **Hero image is optional.** There is no standard hero-graphic style yet, so
134 most articles currently ship without one. If you do set a hero, use
135 `heroImage` (+ required `heroImageAlt`, optional `heroCaption`); it renders
136 full-column-width directly under the title, ahead of the TL;DR, and the build
137 **fails** if `heroImage` is set without `heroImageAlt`.
138- **Where images live.** Put real image files under
139 `apps/web/public/articles/<slug>/` and reference them as
140 `/articles/<slug>/<file>`. Prefer `.webp`/`.png`; keep them reasonably sized.
141- **Schematic app-window cards** (the `mock:<name>` step cards from
142 `StepMocks.tsx`) still work for how-to walkthroughs and are exempt from the
143 figure framing — they render as their own step panel, not a bordered figure.
144 A step item can also carry a nested bullet list and a follow-up paragraph
145 (the step-grid CSS places them in the text column since 2026-07-10). Use
146 that to make the pivotal step the meatiest one — e.g. quoting literal,
147 copy-pasteable rules. Hard-won literal rules are the highest-value quotable
148 content an article can carry; competing articles can't reproduce them.
149- **SEO note:** when a `heroImage` is set, the BlogPosting JSON-LD uses it as
150 the structured-data image (otherwise the title OG card).
151
152## Do not repeat the TL;DR in the intro
153
154The TL;DR (`answerSummary`) already answers the question directly. The first
155body paragraph must do a *different* job: correct the reader's wrong frame, set
156up the stakes, or explain why the obvious comparison is misleading. If the intro
157mostly restates the answerSummary, delete it or rewrite it. A reader who just
158read the TL;DR should learn something new in the first paragraph, not hear the
159same answer twice.
160
161## TL;DR (`answerSummary`) rules
162
163The single most-edited field. Get it right the first time:
164
165- **Short.** Aim ~55–75 words. If it runs long, cut. A four-sentence version beats an eight-sentence one every time.
166- **Conversational.** Use "for example", "like", "say". It should read like you explaining it to one person, not a spec.
167- **Lead with concrete, tiered examples**, never one abstract range. The failure mode to avoid: "a simple workflow costs $3,000 to $30,000." That range is too wide and self-contradictory. Instead, split into named tiers, each with a recognizable example:
168 > A simple tool, like one that drafts replies to routine emails, runs $3,000 to $5,000. A bigger multi-step workflow is more like $20,000 to $30,000, plus $20 to $200 a month to run.
169- **Self-contained.** Someone who reads only these lines should have the real answer.
170- **End on the one thing that matters most** (here: the wrong-workflow warning).
171- **No product/skill plug inside the TL;DR.** A bolded pitch mid-answer dilutes what an answer engine will quote (real edit: the WhatsApp article's TL;DR carried a bolded skill link and ran to 100 words; the fix moved the pitch to its own body section). The TL;DR is the answer; offers live in the body.
172
173## Concrete examples over abstractions (everywhere, not just the TL;DR)
174
175"Something very simple" or "a well-scoped workflow" tells the reader nothing.
176Name the actual tool every time:
177
178- Bad: "Automating a simple workflow costs $3–5k."
179- Good: "A tool that drafts replies to your routine customer emails costs $3–5k."
180
181Reuse the same two or three example tools consistently across the whole article
182(TL;DR, body, stats) so the reader builds a mental model instead of meeting a
183new example in every paragraph.
184
185## Numbers and ranges (mostly cost-specific)
186
187These apply to any article that quotes figures, but they matter most on
188pricing/ROI articles. Do not manufacture tiers or dollar amounts for an article
189that is not about cost.
190
191- **Tier, don't span.** Never attach a giant range to one label. Break it into tiers (simple / multi-step), each with its own tight range and its own concrete example. *(Cost articles especially.)*
192- **Explain the mechanism in plain language, and say who bears it.** *(Cost-specific.)* When you name a cost, don't leave it as jargon. Example that had to be added: the monthly "usage" cost is *the fees the AI models and any connected services (an email API, a search tool) charge each time the tool runs; the integrator wires these up so the technical side is handled, but the usage itself is billed to the company.* Same pattern for any cost, fee, or mechanism: what it is, and whose bill it lands on.
193- **Keep the math honest.** If you quote a payback ("pays for itself in a few months"), the numbers in that example must actually support it. A $20–30k build against $900/month of manual work does NOT pay back in months, so use the cheap-tier example there.
194
195## The "By the numbers" stats strip
196
197- **Stats are optional. If present, use exactly 3 tiles.** Omit the `stats` field entirely on an article with no numbers worth surfacing; when you include it, ship exactly 3. The renderer slices to 3 (`article.stats.slice(0, 3)`), so a 4th is silently dropped and fewer than 3 looks unbalanced.
198- Every stat must map to a number that actually appears in the body. The strip is a scannable index of the article's claims, not new claims.
199- **Pick numbers the reader needs for their decision** (what it costs to run, how long to set up, how long to recover), not facts about the alternative the article rejects. Real edit: an "8-participant cap on official-API groups" tile (a fact about the path the article says not to take) got replaced by total monthly running cost.
200- `value` is a string, so ranges/units render verbatim: `"$3k–$5k"`, `"2–6 weeks"`, `"~1 / month"`, `"< 1 year"`. Use an en dash `–` in ranges, never a hyphen-minus and never an em dash.
201- **Tight labels.** One line. Cut filler. "Per month to run the workflows" not "Per month to run each of the workflows." Put one concrete example in at least one label ("…like drafting routine emails").
202- `icon` is a short key mapped in `ARTICLE_STAT_ICONS`. Valid keys only:
203 `clock`, `calendar`, `rocket`, `target`, `speed`, `wrench`, `repeat`, `coins`, `money`, `chart`, `team`, `workflow`.
204- Optional `sourceUrl` on a stat links the figure to a source pill.
205
206## The CTA / promotions (promo part is cost-specific)
207
208- Every article auto-appends a **shared** book-a-plan CTA (`ctaTitle`/`ctaBody`/`ctaButton` in `ArticleView.tsx`, per locale). Editing that changes it on **every** article. Do not put article-specific copy there.
209- An **article-specific** offer or promo goes in the **body** of that one article, as a final Q&A section that hands off into the CTA below it. Real example (the cost article's launch discount):
210 > ## Is there a discount right now?
211 > Yes. I'm just launching, so I'm taking on a small group of early clients at about half the numbers above. … If you want one of those spots, the free AI plan below is where it starts.
212- When a promo restates numbers ("about half the numbers above"), give the reader at least one concrete resulting figure ("closer to $1,500 to $2,500") and make sure it's arithmetically right against the tiers.
213
214## Voice
215
216- **No em dashes.** Ever. Use commas, or parentheses, or split the sentence. (Hard rule, see the `voice-profile` skill.)
217- Conversational and direct. Short declaratives. "Wrong frame." is a fine sentence.
218- First person as Meir where it's his offer or opinion (the promo, "teaches me the most"). Third person for the general explainer body.
219- Contractions are fine and preferred. Avoid corporate hedging ("it depends", "various factors").
220
221## Sources
222
223- 2–3 real, resolvable URLs. Never invent one. If unsure a link resolves, check it.
224- **A source must support a claim the article actually makes**, not sit there for credibility. Reputable is not enough. If nothing in the piece leans on it, drop it.
225- **The inverse holds too: the article's strongest quotable claim must carry a source.** Real edit: the WhatsApp article's most-quotable fact (the 8-person cap on official-API groups) had no source while a weak X-thread walkthrough sat in the sources list; the fix swapped them. A link that only supports a how-to step belongs inline in the body, not in `sources`. Verify the page states the claim (fetch it) before citing.
226- **Link the specific report or article, not a topic hub.** Point at the page with the finding (`.../state-of-ai-report-2026`), not the outlet's landing page or a tag/search page.
227- **If a number is operator judgment, say so.** Figures like the cost tiers come from experience, not a study. Phrase them as judgment ("in my experience", "typically") rather than dressing them up with a source that does not actually contain them. Do not attach a research URL to a number that research did not produce.
228- Outlets used before (Anthropic, a16z, Stanford HAI, Deloitte, MIT/Fortune, IBM) are examples of the *bar*, not a required set. Pick whatever genuinely backs this article's claims.
229
230## Consistency sweep (do this after any numeric or example edit)
231
232Changing one number or example silently breaks others. After an edit, re-read
233the WHOLE article and confirm:
234
235- The same example tool carries the same price tier everywhere (TL;DR, body, stats, promo).
236- Every stat tile still matches a body number.
237- Any payback/ROI claim still holds against the numbers in its own example.
238- The promo's halved/derived figures are still arithmetically correct.
239- `updatedAt` is bumped if the change is material.
240
241The canonical bug this catches: an invoice-matching workflow priced at $20–30k
242in the cost breakdown while the payback section still called the same invoice
243tool "a few thousand to build." Fix by making the examples consistent, not by
244patching one number.
245
246## Quick checklist before shipping
247
248- [ ] Filename == `slug`; `locale` correct; `status` set intentionally.
249- [ ] Title reads like the question; `primaryQuestion` + `answerSummary` are a clean Q→A.
250- [ ] TL;DR is short, conversational, self-contained (and tiered with concrete examples *if* it's a cost article).
251- [ ] **Intro does a different job than the TL;DR** — it does not restate the answer.
252- [ ] Every H2 is a question; each answered in one tight paragraph; a one-line rule closes it.
253- [ ] **600–900 words; under 1,000.** Cut before adding sections.
254- [ ] Stats optional; if present, exactly 3, tight labels, valid icons, each backed by a body number.
255- [ ] **1–3 bespoke `fig:` figures placed at the article's argument points, each with a caption that carries the takeaway; figure module has en/he/ru labels; localized siblings embed the same figures with translated alt/captions. Hero image optional (with alt text if used).**
256- [ ] No em dashes anywhere. En dashes in ranges.
257- [ ] Sources support actual claims, link the specific page not a topic hub; operator-judgment numbers phrased as judgment, not falsely sourced.
258- [ ] No cost tiers / dollar figures / discount pitch forced onto a non-cost article.
259- [ ] (Cost articles) costs explained in plain language with who-pays; ranges tiered, not spanned; payback math holds.
260- [ ] Article-specific CTA/promo in the body, not the shared component.
261- [ ] Consistency sweep done.
262- [ ] For a new indexable article, add localized siblings later if the family needs them (shared `translationKey`).
263