# Live from my iPhone to my site in under 90 seconds
Source: https://simonbeauloye.com/writing/building-with-ai/publishing-from-my-iphone/
Published: 2026-04-29
Pillar: building-with-ai
Author: Simon Beauloye (https://simonbeauloye.com)
License: CC-BY-4.0 (attribution required)
Cite as: Simon Beauloye, "Live from my iPhone to my site in under 90 seconds", https://simonbeauloye.com/writing/building-with-ai/publishing-from-my-iphone/
AI-use policy: https://simonbeauloye.com/ai-policy.txt
> I'm updating this site with just a few taps on my phone: a small Shortcut, the iPhone share button, and a workflow doing the heavy lifting on the server. See exactly how it works.
## Takeaways
- I wanted a quick and easy way to share what I'm currently reading, watching, or working on, without having to use a CMS.
- I built in an afternoon with Claude Code a small Apple Shortcut that posts to /stream straight from the iPhone share button.
- It takes about ninety seconds from tapping share on my phone to a live page on the site being updated.
- Most of the work, such as cleaning the URL or finding the real headline behind a paywall, happens in a small workflow on the GitHub server, not on my phone. The entire setup is completely free.
## Signals
- Claim: The /stream micro-feed on simonbeauloye.com publishes in about ninety seconds end-to-end, from iPhone share button tap to live page.
Year: 2026
Source: Operating measurement, simonbeauloye.com
- Claim: The Post to /stream iOS Shortcut runs in 11 actions and POSTs a structured GitHub issue to a dedicated workflow that handles the file composition on a runner.
Year: 2026
Source: Operating record, simonbeauloye.com build
- Claim: The /stream content schema defines eight entry types: reading, watching, listening, link, working-on, shipping, travelling, and note.
Year: 2026
Source: Astro content collection schema, simonbeauloye.com
- Claim: When the submitted title matches a known stub pattern such as 'Subscribe to read' or 'Just a moment', the server-side resolver falls back through oEmbed, og:title, twitter:title, JSON-LD name or headline, and the first h1, in that order.
Year: 2026
Source: Operating record, simonbeauloye.com build
- Claim: The workflow fetches paywalled publisher pages identifying as a popular link-preview bot used by messaging apps, because browser-shaped User-Agents are blocked from datacenter IPs by the Financial Times and similar publishers while link-preview bots stay whitelisted.
Year: 2026
Source: Operating record, simonbeauloye.com build
- Claim: The hand-curated source map covers roughly thirty outlets including FT, WSJ, NYT, Bloomberg, Stratechery, and Apple Podcasts, mapping each hostname to a short label and a full publisher name.
Year: 2026
Source: Operating record, simonbeauloye.com build
## Article
When redesigning my personal website, I wanted a quick and easy way to share the things I'm reading, watching, listening to, or working on, directly from my phone, without having to create a proper CMS or login flow. The solution I built is a small Apple Shortcut on my phone that posts directly to a micro-feed on this site at simonbeauloye.com/stream. Tap the share button , pick a category, and the page is updated within 90 seconds.
**All completely free and running on GitHub actions.**
This piece is a quick walk-through of why I wanted it, what I built with an AI agent on a Saturday afternoon, and what's doing the work behind the scenes.
## Why I wanted something this lightweight
I wanted a place to share on this website things that I found interesting online, but it had to be as easy as sharing a link with my friends on WhatsApp.
When Claude Code suggested to build a [/stream page](/stream/), I only agreed to implement the idea if we could find a solution that would sync from my phone. I didn't want to have to open a code editor on my laptop each time I wanted to share an article, a video, or a podcast.
The stream page is the closest thing on this site to a feed. It's a list of articles I'm reading, podcasts I'm listening to, videos I'm watching, projects that I'm working on, or places I'm travelling to. There are eight categories in total, plus a free-form note. Each entry is a couple of lines of text and a link.
The whole point of a feed like this is that it's easy to update.
So the design constraint was simple. I wanted the iPhone share button to be the publishing UI. When I read something good in an app on my phone, I should be able to tap Share, choose "Post to /stream", and have the content live on my website shortly after. No login, no second device, no manual sync, no opening a laptop later to "tidy it up."
**But it had to be secured too**. I don't want anyone else to be able to publish content on my site.
My constraints ruled out the obvious options. A CMS adds a login-and-format step. A headless service like Notion, Airtable, or Sanity adds a sync step. Both turn a ten-second action into a few minutes of back and forth between different apps. I knew I wouldn't do that.
The only things we could work with were an Astro site with content stored as plain MDX files in a Git repo, and my iPhone with iOS Shortcuts. The job was to connect those two cleanly enough that the share button became the editor.
## What I built, in plain English
The version that's running today has two parts: a small Shortcut on my phone, and a small workflow on the server.
The Shortcut is what I see. When I tap Share on a page in Safari and pick "Post to /stream," it grabs the URL, fetches the page's title for me, and asks me three quick questions: "Is this title right?" (with the auto-fetched answer pre-filled, so usually I just tap OK), "What kind of entry is this?" (I pick from the eight types), and "Anything to add?" (an optional one-liner of context). That's it. The Shortcut quietly hands all of that off to the GitHub repo, and I get a notification a moment later that says "Posted to /stream."
The workflow on the server is what I don't see. It receives the four fields the phone sent, cleans the URL, double-checks the title (more on that below), figures out which publisher the link is from, formats everything correctly, writes it as a new file in the site's content folder, commits it, and lets the rest of the site's normal deploy pipeline take over. About ninety seconds later, the entry is live at [simonbeauloye.com/stream](/stream/) and the cycle is done.
**Two things make this work,** more than any individual piece of code: the split of responsibilities and the fact that nothing about the architecture is exotic.
The phone collects four fields. The server does everything that requires logic, fetching, or judgement. The deploy pipeline that ships the rest of the site ships the new entry as well, because the new entry is just another file in the same place all the other content lives.
Here are the most recent entries by type, pulled live from /stream as I write this:
## What does the server do behind the scenes?
If you're curious about what the workflow is doing, here's the slightly nerdier walk-through. Skip ahead if it's not your thing.
The single most useful piece of work the server does is figuring out the right title. The phone sends whatever happens to be in the page's `
` tag, which is fine for clean articles but unreliable everywhere else. A paywalled site might return "Subscribe to read." YouTube on a desktop browser sometimes returns just "YouTube." A Cloudflare-challenged page returns "Just a moment." None of those are titles I want stored as the title of a stream entry.
So the workflow runs a small fallback cascade. If the title from the phone matches a list of known "stub" patterns (paywall lines, bot-wall lines, JS-rendered site-name lines), the server quietly ignores it and goes hunting. It tries oEmbed first for video sites like YouTube and Vimeo, because oEmbed is an official API that returns clean JSON. If that doesn't apply, it fetches the page's HTML and looks at, in order, `og:title`, `twitter:title`, JSON-LD `name` or `headline`, and finally the first ``. Whichever returns something that isn't another stub wins.
The wry detail is the User-Agent the workflow uses. Paywalled publishers like the Financial Times tend to return an HTTP 403 to GitHub Actions runners (which sit on datacenter IPs) for any browser-shaped UA. Chrome, Googlebot, Twitterbot, facebookexternalhit, and LinkedInBot all hit the wall. I had to be creative to find a UA that consistently passed. The pattern, once you see it, is sensible: paywalled publishers want their share cards to render in messaging apps, so the link-preview bots get whitelisted. The workflow now identifies as one of those popular messaging apps.
There's a safety net underneath all of that. If the workflow tries every fallback and still can't find a real article title, instead of failing loudly or storing a stub like "Security Verification" as the entry's headline, it quietly publishes the entry as a draft. The URL and any note I added are preserved, the entry lands in the repo, but it doesn't appear on the site until I edit it by hand. That decision came out of an obvious operational question: if the fetch fails for some unexpected reason, do I want a hard error that loses the URL, or a soft fallback that I can clean up at my leisure? Soft always wins.
A few extra refinements finish up the workflow:
- Tracking parameters get stripped from the URL (`utm_*`, `fbclid`, `gclid`, and friends)
- HTML entities get decoded so I don't get `&` showing up in titles
- A hand-curated map of about thirty publishers (FT, WSJ, NYT, Bloomberg, Stratechery, Apple Podcasts, and so on) maps a hostname to a short label like "FT" and a full publisher name like "Financial Times," so the source field renders cleanly and any " | Financial Times" suffix gets stripped from the title
None of those are individually interesting, but together, they make the feed feel considered instead of just a raw dump.
The whole thing is the kind of plumbing a [non-engineer operator](/glossary/non-engineer-operator/) (someone who ships production software without an engineering background, using AI-assisted tools to build the systems they would previously have hired an engineer for) can put together over a few hours. Claude Code wrote most of the code inside the workflow. I wrote the architecture, made the decisions about where each piece of logic should live, and reviewed the diff.
The whole project is a small, satisfying example of what AI-assisted building feels like when the operator stays close to the design and lets the model do the typing.
## Where I'd like to take this next
The next page on my list is the [/now](/now/) page. I'd like a separate Shortcut that lets me update a small location pin from my phone, so the page stays fresh without a laptop. The architecture should be the same shape as this one. Phone collects, server composes, the rest of the site doesn't care.
> **Update:** This one is now live, and even easier than the /stream Shortcut. One tap updates the city and country shown on [/now](/now/), and the precise GPS coordinates from the phone are stripped on the server before anything is committed. Privacy-first by construction.
If any of this sounds like something you would like to build for your own site, or if you have ideas for how I could make it better, I'd love to hear from you. The Shortcut spec, the workflow YAML, and the token-scoping write-up are all things I'm happy to share. Find me on [LinkedIn](https://www.linkedin.com/in/simonbeauloye/), [X](https://x.com/simonbeauloye), or by email at simon@moonshotdigital.com.
## See also
- [Site index](https://simonbeauloye.com/llms.txt)
- [Full corpus](https://simonbeauloye.com/llms-full.txt)
- [Pillar index (building-with-ai)](https://simonbeauloye.com/llms/building-with-ai/llms.txt)
- [Pillar hub (building-with-ai)](https://simonbeauloye.com/writing/building-with-ai/)
- [AI-use policy](https://simonbeauloye.com/ai-policy.txt)
### Glossary terms referenced
- [The non-engineer operator](https://simonbeauloye.com/glossary/non-engineer-operator/) — The non-engineer operator is the persona of someone who ships production software without an engineering background, using AI-assisted development tools to build the systems they would previously have hired engineers to build.