Read more of this story at Slashdot.
Read more of this story at Slashdot.
Meta now lets you make your own Muse gadgets that feature the company's new AI agent with code that the company open sourced. The company suggests projects like loading Muse on a color E Ink display to show reminders, adding it to an HDMI stick so you can display Muse on a big screen, or putting Muse on a small touchscreen device to make what looks kind of like a DIY Muse Charm.
"Muse gadgets are open source devices you build yourself," Meta says. "Program an off-the-shelf ESP32 board or set up a Raspberry Pi with our SDKs, then connect Muse to your displays, buttons, sensors, actuators, and whatever else you've got lying on your workbench. β¦
I talk about this so often in coaching that I sometimes forget whether I ever wrote it down. I don’t think I have, so here goes…
Yesterday I asked a founder whether we had covered the enterprise cycle and the small business problem. He said no. So, I did.
The 18-month rule: enterprises do not adopt new things on a clock shorter than about 18 months. Pilots, reviews, analysis, and politics stretch the path from “interesting” to “they pay what you think the thing is worth.”
It seems this is a lesson founders have to learn themselves. I’ve lost count of the startups I’ve advised who make enterprise their primary market, ignoring this, and then come back and tell me they should’ve listened to me.
How do you counter it?
If bigger businesses really are the sweet spot, the best bet is what the PC did: It snuck in under people’s desks without IT knowing.
For example, if you are building hiring software, you are not selling to HR as a department. You are talking to hiring managers who have budget and freedom. The catch is fragmentation. How do they find you? How do you find them? How do you price under their project budget and still run a business? Doable. Hard.
A champion inside a giant bureaucracy is gold. Better still if they can pay from a project budget instead of waiting on an enterprise subscription motion. A pilot that “will turn into a subscription soon” is a lot like engineering based on hope; it rarely turns out well. Be intentional about what the engagement is for: Is it revenue now, or proof that the pain is real and your product makes it go away? Those are different goals and require very different motions.
I first really understood the small business problem while building Windows Home Server, with Small Business Server as the sister product. It has only gotten clearer since.
You can pick a vertical, say local machine shops or engineering shops, do the math, and prove that tens of thousands of them spend billions a year on hiring software. The slide looks great. What early-stage companies fail to recognize is the problem I call The Small Business Problem.
The Small Business Problem is fragmentation of reach. Unless you are Microsoft, Intuit with QuickBooks, or Verizon, you cannot get in front of all 10,000 shops in that vertical.
Small Business is a lot like Consumer, where the things you can control are friction and awareness. The product has to be easy to discover, easy to start, easy to get value from, and easy to keep using. Latency is friction. Awareness and satisfaction (NPS and the like) matter more than almost anything else.
I do not think most early-stage businesses have the resources to chase both. Pick one.
If you pick enterprise, design for champions, and “getting under the department’s desks”. Or, have the funding to last for more than 18-months.
If you pick small business, design for reach and near-zero friction, and stop pretending a “Book a demo” button is onboarding.
The post The 18-Month Rule and the Small Business Problem first appeared on tig.log.This article provides a step by step guide to publishing one markdown article to dev.to, Medium, AWS Builder Center and LinkedIn with publishing-kit, an agent skill for Claude Code, Codex and Antigravity. The article you are reading was published with it, and every command output below comes from that run.
https://github.com/xbill9/publishing-kit
One markdown file goes in. A dev.to draft, a Medium story, a Builder Center draft and a LinkedIn post come out, each one checked before it ships.
Markdown is the easy part. You write headings, a table, a few code blocks and a cover image, and it looks right in your editor and on GitHub.
Then you publish it in four places, and each one treats that file differently:
| Destination | Publishing API | Tables | Multi-line code | Cover |
|---|---|---|---|---|
| dev.to | π’ full REST API | π’ native | π’ native | URL, cropped to 2.381:1 |
| Medium | β unsupported since 2023 | β dropped | β one line | first image in the body |
| AWS Builder Center | β none | π’ native | π’ line-numbered | 1200x675 upload |
| β οΈ posts only, no drafts | β none | β none | link card or upload |
Every one of those differences fails without an error. You get a plausible-looking page with a missing table, a code block run together on one line, or a cover with its title cut off, and you see it after it is live.
Medium has two ways in, and they disagree with each other.
The importer (medium.com/p/import) brings in prose, headings, links and images from a URL. It drops markdown tables entirely, flattens <pre> blocks to a single line, strips HTML comments, and renders only two heading sizes, so ## sections all read as titles. A link inside an image caption makes the whole image disappear. It also caches by URL and ignores the query string, so re-importing a fixed page with ?v=2 brings back the old one.
Pasting into the editor keeps multi-line code, but removes any image embedded as a data: URI, with no placeholder left behind.
The API would avoid all of this, and Medium's own documentation now opens with "The Medium API is no longer supported. We do not recommend using it." The repository was archived in 2023.
So Medium can only be reached by driving its editor in a browser, with its quirks known in advance.
dev.to has a complete REST API: create, update, list, and route to an organization. It renders markdown with hard line breaks on, so a source file wrapped at 80 columns publishes with a break in the middle of every paragraph. It displays the cover through a 2.381:1 crop, which cuts the top and bottom off a 16:9 image. And an update through the API sends the front matter's published: false along with the body, which takes a live article back to draft.
AWS Builder Center has no publishing API. The body goes in by pasting into a browser editor, and its publish step checks every link, including URLs written as plain text, and refuses with a message that names none of them.
LinkedIn has a Posts API, but PUBLISHED is the only state it accepts on creation, so anything posted through it goes straight to your feed. The post text renders no markdown at all.
It packages the workarounds as an agent skill plus a set of small Python scripts. The skill tells the agent what each destination needs; the scripts do the parts that should be exact.
make-medium.py renders tables to images and writes Medium HTML, make-builder.py writes the Builder Center version, make-linkedin.py writes the post.make-cover.py draws one design at every geometry the destinations need and names each file by a hash of its bytes.preflight.py checks the cover, the front matter, the prose, the links and every number in the article, and exits non-zero.publish-devto.py posts to dev.to with no browser.pandoc for the Medium build.~/.devto.key or $DEV_TO_API_KEY.In Claude Code:
/plugin marketplace add xbill9/publishing-kit
/plugin install publishing@publishing-kit
In Codex:
codex plugin marketplace add xbill9/publishing-kit
codex plugin add publishing@publishing-kit
When you want to run a script by hand, ask the skill where it lives:
python3 skills/publishing/scripts/skill-footprint.py --where
/home/xbill/publishing-kit/skills/publishing
Most of the time you do not run the scripts yourself. You ask the agent to publish, and it runs them.
The source is a dev.to markdown file with front matter, because dev.to renders tables, code and emoji natively. Everything else is derived from it. This is the front matter of this article:
---
title: "Write Markdown Once, Publish It Everywhere: dev.to, Medium, AWS Builder Center and LinkedIn"
published: false
description: "Markdown is easy to write and hard to publish. ..."
tags: writing, markdown, devtools, ai
cover_image: https://raw.githubusercontent.com/xbill9/publishing-kit/main/articles/markdown-publishing-woes/cover.168992c6.jpg
---
published: false stays in the file. Going live is a separate command, so a routine update never publishes by accident.
The prompt that started this article was one sentence: "write another article that explains what this skill does, step through how to use it and publish it, and dogfood the article with the kit."
python3 make-cover.py --out cover.jpg --sizes devto,builder --flow --no-text \
--dest "dev.to||blue" --dest "Medium||orange" \
--dest "Builder Center||orange" --dest "LinkedIn||muted" \
--content-address --url-base "https://raw.githubusercontent.com/xbill9/publishing-kit/main/articles/markdown-publishing-woes"
wrote cover.168992c6.jpg 1376x578 44 KB
wrote cover-builder.712a395f.jpg 1200x675 39 KB
https://raw.githubusercontent.com/xbill9/publishing-kit/main/articles/markdown-publishing-woes/cover.168992c6.jpg
https://raw.githubusercontent.com/xbill9/publishing-kit/main/articles/markdown-publishing-woes/cover-builder.712a395f.jpg
The cover is an illustration with no text: one page, with light fanning out of it to one shape per destination, each in that destination's colour. A cover is first seen as a small card in a feed, where labels and numbers are too small to read and only shape and colour carry. Builder Center's editor also advises against text in cover images.
One design, two sizes: 1376x578 for dev.to, which is exactly the 2.381:1 shape it displays, and 1200x675 for Builder Center's upload. The hash in each filename means a regenerated cover is a new URL, so no cache can serve the old picture.
git add articles/markdown-publishing-woes
git commit -m "articles: write once, publish everywhere"
git push
dev.to fetches the cover from its URL every time the page renders, and Medium fetches the table images when it imports. A file that exists only on your disk shows up as a broken image.
python3 preflight.py devto-markdown-publishing-woes.md --live
==============================================================
SUMMARY
==============================================================
PASS facts
PASS prose
PASS article
PASS links
FAIL linkedin
1 check(s) failed: linkedin
At this point the only failure is the LinkedIn post, because its links to the Medium and Builder Center versions are still PENDING. Everything the dev.to draft needs has passed.
--live fetches every published URL and compares the served bytes with the file on disk, and fetches every link in the article the way Builder Center's publish step does. Without it the checks reason only about local files.
python3 publish-devto.py --create devto-markdown-publishing-woes.md --org-slug gde
ok published: false
ok title present
ok description present
ok tags present
ok devto-markdown-publishing-woes-hosted.html image URLs resolve to markdown-publishing-woes
ok 3 medium/img image(s) committed and matching HEAD
ok no hard-wrapped paragraphs
ok no stale counts of the kit's own parts
ok no empty link targets
0 fail, 0 warn
created 4788671
4788671 draft org=- Write Markdown Once, Publish It Everywhere: dev.to,
https://dev.to/xbill/write-markdown-once-publish-it-everywhere-devto-medium-aws-builder-center-and-linkedin-48m7-temp-slug-1340266
routed to gde (11939)
The same file goes to a second community with a second --create. This article is also published under AWS Community Builders, and the two copies are byte-identical; only the organization differs:
python3 publish-devto.py --create devto-markdown-publishing-woes.md --org-slug aws-builders
created 4788689
4788689 draft org=- Write Markdown Once, Publish It Everywhere: dev.to,
https://dev.to/xbill/write-markdown-once-publish-it-everywhere-devto-medium-aws-builder-center-and-linkedin-314p-temp-slug-1345346
routed to aws-builders (2794)
--create runs the article checks first and refuses on any failure. The front matter is part of the payload, so the title, tags and cover arrive with the body, and the paragraphs are unwrapped on the way out. The result is a draft.
python3 make-medium.py devto-markdown-publishing-woes.md medium --cover=cover.168992c6.jpg
devto-markdown-publishing-woes.md: 2 tables, 0 diagrams
USE THIS -> medium/devto-markdown-publishing-woes-hosted.html (paste or import; needs medium/img committed AND pushed)
not this -> medium/devto-markdown-publishing-woes-embed.html (201 KB; data: URIs, Medium drops them all on paste)
Medium never fills its Title field from pasted content -- set the title separately.
Both tables in this article are now PNGs under medium/img/, rendered at twice the display size. -hosted.html points at them by their public GitHub URL, so Medium fetches and re-hosts them. Code blocks stay as code, because pasting keeps multi-line code where the importer would flatten it.
The agent then opens Medium in the browser and pastes the hosted HTML into a new story. The title is typed into its own field, because no paste or import route fills it.
python3 make-builder.py devto-markdown-publishing-woes.md --out builder-markdown-publishing-woes.md \
--title "Write Markdown Once, Publish It Everywhere"
ok no emoji
ok widest table is 5 columns
ok no duplicate AWS disclaimer (the platform adds its own)
ok title and subtitle carried as strippable lines
Emoji come out, because Builder Center's house style has none, and front matter comes out, because title and description are separate fields there. The agent serves the body from serve-body.py on the same machine, carries it into the editor tab in window.name, compares a checksum on both sides, checks that the editor is empty, and pastes once.
python3 make-linkedin.py devto-markdown-publishing-woes.md
devto-markdown-publishing-woes.md -> linkedin-devto-markdown-publishing-woes.txt
FAIL 3 link(s) still PENDING: builder, devto-gde, medium
ok no draft URLs; every slug is settled
ok hook fits the fold: 91 chars
ok post is 832 chars of 3000
ok no markdown left; LinkedIn renders none of it
ok no template scaffolding left
ok no Unicode pseudo-bold
The post is a text file plus the cover fitted to LinkedIn's image size. Its links come from links.txt beside the article, and a link still marked PENDING fails the run, so a post cannot go out pointing at a page that does not exist yet. The run above is from before the drafts were published; once each destination is live, its URL goes into links.txt and the run passes.
Every destination is now a draft. --list shows the dev.to one, already routed to the organization:
python3 publish-devto.py --list
30 draft(s)
4788671 draft org=gde Write Markdown Once, Publish It Everywhere: dev.to,
https://dev.to/gde/write-markdown-once-publish-it-everywhere-devto-medium-aws-builder-center-and-linkedin-48m7-temp-slug-1340266
Going live is one deliberate step per destination. For dev.to it is publish-devto.py --publish 4788671. dev.to ignores a published: true sent on its own, so --publish resends the body with the front matter flipped and then confirms from your article listing. Medium and Builder Center are one click on Publish in the browser, and the LinkedIn post is pasted into the composer with the cover attached.
published: false in the Source
The pre-flight requires it, and it is what makes an update safe. After updating an article that is already live, run --publish <id> again and check --list, because the update carried the draft flag with it.
Medium and Builder Center editors reject typed keystrokes in a background tab, hide upload buttons inside shadow DOM, and duplicate a paste if the editor was not empty. The kit's in-page helpers check each of those before acting, so the browser steps are safer in the agent's hands.
| Destination | How it gets there | Built by | Draft first? |
|---|---|---|---|
| dev.to | REST API π₯ | publish-devto.py |
π’ yes |
| Medium | browser paste | make-medium.py |
π’ yes |
| AWS Builder Center | browser paste | make-builder.py |
π’ yes |
| composer | make-linkedin.py |
β οΈ composer only |
Write in dev.to markdown and publish there first. It is the only destination with a complete API, it renders everything the source contains, and its draft link is the first one the other versions can point at. Medium and Builder Center follow from the same file, and the LinkedIn post goes last, once every link it carries resolves.
The goal of this article was to explain why publishing markdown to more than one place goes wrong, and to publish this article to four destinations with publishing-kit. The key to the solution was one source file, a generated artifact per destination, and a pre-flight that fails before anything ships. The results were:
Scope: one article, published on 2026-10-02 with publishing-kit 0.30.0 from Claude Code on Linux, to the dev.to gde and aws-builders organizations, Medium, AWS Builder Center and LinkedIn. Destination behaviour described above comes from the dated measurements recorded in the kit's skill and reference files.
The strategy for publishing one markdown article to four destinations with an agent skill was validated with an incremental step by step approach.
Ranjan Roy from Margins is back for our weekly discussion of the latest tech news. We cover: 1) Anthropic's IPO S-1 document leaks 2) Anthropic's revenue growth 3) Anthropic's funding commitments 4) Does the entire stock market hinge on Anthropic pulling it off? 5) Record low S&P 500 breadth 6) Would Big Tech abandon Anthropic if things go wrong? 7) OpenAI introduces its Dots personal agent 8) Alex's Dots review 9) Do you really need frontier models for these AI assistants? 10) Tavus and the visual turning test 11) Shrimp Jesus, avatar style
---
Enjoying Big Technology Podcast? Please rate us five stars βββββ in your podcast app of choice.
Want a discount for Big Technology on Substack + Discord? Hereβs 25% off for the first year: https://www.bigtechnology.com/subscribe?coupon=0843016b
Learn more about your ad choices. Visit megaphone.fm/adchoices