← Engineering
Making AI-built browser games playable inside X posts
By Vladimir Glazachev · October 10, 2026
TLDR: Any published Rosebud game now plays inside an X post. Paste the game's link and followers press play in their feed. This is what it took.
Player Cards
X renders an iframe instead of a picture when a page declares a Player Card. When the link is posted, X's crawler reads four tags from the game page:
<meta name="twitter:card" content="player">
<meta name="twitter:player" content="https://rosebud.ai/embed/<game>">
<meta name="twitter:player:width" content="720">
<meta name="twitter:player:height" content="720">
The feed shows a compact card with a play button. Pressing it loads the iframe in the post at the declared aspect ratio.
What we built
- Player tags only for X. The game page sends
twitter:card=player only to Twitterbot. Discord, Slack and iMessage keep the large-image card. Game pages are private, no-store, so the two versions can't mix in a cache. X also gets a short title: <game> on Rosebud.
- A dedicated
/embed/<game> route with its own root layout: the game runtime and the anonymous session, nothing else. Reusing the game page with ?embed=1 rendered the site navbar until hydration, so the card flashed the website first.
- Framing.
/embed sends frame-ancestors for x.com and twitter.com only. The game runs one level deeper on our runtime host, so the chain is x.com, then rosebud.ai/embed, then the game.
- Isolation. Games that need
SharedArrayBuffer get COOP/COEP headers per game, as on the regular game page.
- Square sizing. On desktop the game renders into a 720×720 viewport and scales down to the roughly 512-pixel card, because most games' HTML UI breaks in a small viewport. On touch devices it uses the real frame size so buttons stay tappable.
- Loading and failure. The game loads behind a blurred preview. Older-format games get the same cover, lifted on load or after ten seconds. A deleted game shows a compact "not available" screen instead of our full-site 404.
- Controls. A Rosebud icon and a Play on Rosebud button in the bottom corners, at 70% size with a full 44-pixel tap area on touch.
Gotchas
- The new route passed tests and dev mode, then failed the production build. Next.js Cache Components needs routes that read per-request data to opt out of prerendering (
instant = false).
- Staging blocks every crawler in robots.txt, including X's. We allow Twitterbot there so staging links unfurl as real cards.
- X caches cards, so links shared before the change turn playable as X re-reads them.
- Inline play depends on X and the viewer's client. Everywhere else it's a normal link.
Try it: make a game on rosebud.ai, publish it, and post the link. Or play the one in our post.