# Medium Browser Publisher

> Use this skill when the user has explicitly approved a drafted Medium article and it needs to be published through browser automation. Load the latest draft, verify the authenticated Medium editor state with browser snapshots, publish conservatively, and return the verified live URL over WhatsApp.

- Skill: `arvindrk/medium-browser-publisher` (Agent Skill)
- Install (CLI): `npx skillmds@latest add arvindrk/medium-browser-publisher`
- Raw SKILL.md: https://api.skillmd.com/api/skills/arvindrk/medium-browser-publisher/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: arvindrk (https://skillmd.com/u/arvindrk)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/arvindrk/medium-browser-publisher

---


# Medium Browser Publisher

Publish a previously drafted Medium article using browser automation with a persistent profile. This skill is the final publication step and must behave conservatively.

## When to Use This Skill

Use this skill when:

- a current draft exists and the user clearly said `publish`, `approve`, `post`, or similar
- the pipeline is in an approval-complete state and needs final Medium publication
- a live URL must be produced and confirmed

Do not use this skill to write drafts, choose topics, or infer approval from ambiguous messages.

## Mission

Take an approved draft, open Medium's new-story flow, populate the article, publish it, and return the live URL to the user.

Your priorities are:

- accuracy
- safety
- idempotence
- explicit verification before publishing

## Preconditions

Do not publish unless all of the following are true:

- a draft exists in shared memory or is provided directly
- the user has clearly approved publishing
- a persistent browser profile is available
- the Medium session appears authenticated

If any precondition is missing, stop and ask for the missing piece.

## Shared Memory Contract

Read from:

- namespace: `tech-medium-pipeline`
- key: `latest_draft`
- namespace: `tech-medium-pipeline`
- key: `conversation_state`

If available, expect fields equivalent to:

```json
{
  "title": "Draft title",
  "subtitle": "Draft subtitle",
  "body_markdown": "# Title\n...",
  "tags": ["AI", "Startups"],
  "featured_image_path": "/path/to/image.png",
  "markdown_path": "/Users/.../drafts/2026-04-04-topic.md"
}
```

`featured_image_path` may be `null` if image generation was skipped or failed during drafting. Treat `null` and a missing key identically: skip the image upload step and proceed to publish without a hero image. Do not block publication because an image is absent.

After a successful publish, write back to:

- namespace: `tech-medium-pipeline`
- key: `latest_publication`
- namespace: `tech-medium-pipeline`
- key: `conversation_state`

Use a structure equivalent to:

```json
{
  "published_at": "ISO-8601 timestamp",
  "title": "Published title",
  "url": "https://medium.com/...",
  "tags": ["AI", "Startups"],
  "source_markdown_path": "/Users/.../drafts/2026-04-04-topic.md"
}
```

Set conversation state to:

```json
{
  "phase": "published",
  "last_action": "article_published",
  "last_updated_at": "ISO-8601 timestamp"
}
```

## Browser Requirements

Use the browser tool with a persistent profile. The browser session should preserve the user's Medium login.

Always use `browser.snapshot` before and after important state-changing actions, especially:

- after loading Medium
- before typing into any major field
- after inserting title and subtitle
- after pasting the article body
- after opening the publish flow
- after confirming tags
- after final publish

Do not blindly click through unknown UI states. Snapshots are mandatory evidence.

## Defaults and Gotchas

- Default to stopping when login state, draft identity, or approval state is unclear.
- Medium's editor can change over time; rely on visible labels and fresh snapshots, not brittle assumptions.
- If Medium lacks a dedicated subtitle field, place the subtitle as a standfirst below the title instead of dropping it.
- A saved draft is not a published article; only a verified live story URL counts as success.

## Publication Flow

### Step 1: Load Medium

Open:

```text
https://medium.com/new-story
```

Verify via snapshot that:

- the user is logged in
- the editor is visible
- the page is interactive

If Medium shows a login wall or onboarding interruption:

- do not continue as if published
- ask the user to restore the login session

### Step 2: Resolve Article Components

Prepare the content before typing:

- title
- subtitle
- body markdown
- tags
- featured image path if provided

If the draft is missing a subtitle, derive one that matches the article.

If Medium does not expose a dedicated subtitle field, insert the subtitle as a short standfirst immediately below the title at the top of the story body.

If the tags list exceeds Medium's UI limits, keep the most relevant tags first.

### Step 3: Insert Content Carefully

Populate the story in this order:

1. title
2. subtitle in Medium's subtitle field when available, otherwise as the first standfirst line below the title
3. body markdown or editor content
4. featured image if provided
5. publish metadata such as tags

When pasting body content:

- preserve readable structure
- keep headings and paragraphs intact
- verify formatting in the editor after insertion

If Medium does not accept raw Markdown cleanly:

- paste in the cleanest editor-compatible form available
- preserve semantic structure rather than exact Markdown syntax

### Step 4: Pre-Publish Safety Check

Before pressing the final publish button, verify from the browser state that:

- the title is correct
- the body is present and non-empty
- the draft is the intended article
- the user approval is explicit and recent
- the correct tags are entered

If anything looks wrong, stop and fix it before publishing.

### Step 5: Publish

Complete the final publish action only after the safety check passes.

Then:

- wait for navigation or publish confirmation
- capture another snapshot
- extract the live article URL
- confirm the URL is a real Medium story URL, not a draft or editor URL

## Featured Image Handling

If a valid image path is provided:

- upload it through the Medium editor UI
- verify the image appears in the story

If no image is provided:

- proceed without blocking publication
- do not invent an image file

## WhatsApp Delivery

After success, send a concise WhatsApp message that includes:

- the published title
- the live Medium URL
- a short confirmation that the article is now live

If stats are visibly available at publish time, include them. Example categories:

- estimated read time
- tags used
- publication destination if visible

Do not invent analytics that are not shown.

## Failure Handling

- If the Medium UI changes, rely on fresh snapshots and visible labels instead of brittle assumptions.
- If publishing fails mid-flow, preserve the draft and report the exact blocking point.
- If the URL cannot be extracted, search the current page state and recent navigation before reporting failure.
- If the editor appears to autosave but not publish, treat that as not published.

## Guardrails

- Never publish without explicit approval.
- Never claim the post is live without a verified live URL.
- Never overwrite a different draft if the editor already contains unrelated content.
- Never continue through unclear dialogs or warnings without understanding them from the snapshot.
- Never fabricate stats.

## Completion Checklist

Before ending:

1. Confirm explicit approval exists.
2. Confirm the Medium editor loaded in an authenticated session.
3. Take required snapshots before and after major actions.
4. Publish only after the pre-publish safety check passes.
5. Extract and verify the live URL.
6. Save publication metadata to shared memory.
7. Send the result to the user on WhatsApp.

