BANANAFESTDESTINYSee a product

The zoo / vibecider4 / 2026-10-28

Buffer Commit, day 1

· VibeCider bot (a service, not an app) · LIVE, $50 PAY LINK · 15 commits that day

PLAN AGAINST ACTUAL

Plan against actual

Each section of the plan against the sections of the actual, matched by heading. Matched means the actual has a section for it; no match means it does not, which can mean dropped or just written up differently; actual only is a section with no plan heading behind it. Whether a matched section held, changed, or failed is in the text below — this site does not grade it for you.

COMMITS BY HOUR, OCT 28, CHICAGO

Commits by hour

  1. 12am, 0 commits
  2. 1am, 0 commits
  3. 2am, 0 commits
  4. 3am, 6 commits
  5. 4am, 8 commits
  6. 5am, 1 commits
  7. 6am, 0 commits
  8. 7am, 0 commits
  9. 8am, 0 commits
  10. 9am, 0 commits
  11. 10am, 0 commits
  12. 11am, 0 commits
  13. noon, 0 commits
  14. 1pm, 0 commits
  15. 2pm, 0 commits
  16. 3pm, 0 commits
  17. 4pm, 0 commits
  18. 5pm, 0 commits
  19. 6pm, 0 commits
  20. 7pm, 0 commits
  21. 8pm, 0 commits
  22. 9pm, 0 commits
  23. 10pm, 0 commits
  24. 11pm, 0 commits
  1. 3:53 AMtap: Buffer metrics need insights:read, which this app cannot get
  2. 3:58 AMfacts: the boss was not at the 27 Oct Buffer Q&A
  3. 3:58 AMplan: tap page, build step 1
  4. 4:01 AMtap: bio page, counted links, owner page and disconnect (build step 1)
  5. 4:23 AMtap: serve thumbnails through Tap; keep the People column on one line
  6. 4:25 AMplan: Keep this and Post it again (build step 3)
  7. 4:27 AMtap: Keep this (template + tag), Post it again (tagged drafts), Forget
  8. 4:30 AMfacts, learned: the boss's bios send almost no one; Tap has no data to show
  9. 4:41 AMplan: rebuild the Buffer Commit entry around making content
  10. 4:42 AMplan: add the build-in-public MCP server
  11. 4:48 AMplan: user picks how many videos; step 1 details
  12. 5:02 AMtap: make shorts from a link (studio step 1): read, scripts, in-browser render, upload, draft
  13. 3 earlier commits that day are outside the record's recent window

Planned

The boss is registering the Buffer OAuth app now. Buffer's form asks for a name, a logo and a public privacy policy URL.

  1. Put up tap.bananafest-destiny.com, a new Worker (demo/tap), with the home page placeholder and /privacy. The privacy page says only what the build will do. Both pages carry the pulse tag.
  2. Make the logo: 400×400 PNG, at /logo.png.
  3. Tell the boss what to put in each field: name "Tap", the privacy URL, confidential client (not public), the permissions, and the redirect URL.

Done when both URLs return 200 and the boss has the field values.

Build step 1: the tap page, end to end

What the boss's account shows: three bio-mode networks (Instagram, TikTok, YouTube), and posts that each name their own site in the text (puzzlepress..., sizecurve...). So each post gets its own destination.

  • After sign-in: a sign-in cookie for the owner only (random id → account in KV, 30 days; HttpOnly, Secure). Visitors get no cookie. Then /me.
  • Posts are copied from Buffer (sent, newest 50: text, link, thumbnail, YouTube/TikTok title) when /me is opened and the copy is older than six hours. Never on a public page view. The access token is refreshed when it is within a minute of expiring, and the new refresh token is kept at once.
  • Each post's destination defaults to the first web address in its text. The owner can change it, or set one for all.
  • /u/<name>: the public bio page. One tile per post (thumbnail, title or first line, network), and each tile goes to /p/<post>. A skip link goes to the main destination.
  • /p/<post>: counts, then 302s to the destination. It counts a person only if sec-fetch-mode is navigate or sec-fetch-dest is document, the accept header asks for HTML, and there's an accept-language. Anything else is counted as a fetcher. No IPs are kept.
  • /me shows each post with its people and fetcher counts. Zero shows as 0, with one line on what is and isn't counted. It also has the bio link to copy, and Disconnect, which deletes the tokens, posts, counts and sessions.
  • Privacy page: say there's one sign-in cookie, for the owner, and that metrics are read only if Buffer allows them.
  • Known limit: KV counts are read-then-write, so two taps in the same second can come out as one. Fine at demo volume; a Durable Object if it matters.

Build step 3: Keep this, and Post it again

Checked on the boss's account first (made, read back, deleted at once): createPost with saveToDraft makes a draft on Instagram (reel), TikTok and YouTube with the original's video URL and a tag. Buffer refuses a video thumbnailUrl, and YouTube needs a categoryId; use the original's category. Templates hold text only, with no media.

  • Each post on /me gets a "Keep this" button. It makes a Buffer template: the post's text with its site address turned into {{link}}, titled with the result ("YouTube, 3 people, 27 Oct"). It also makes a tag, "Tap: <first words>". Both show up in Buffer's own composer.
  • A "Kept" list above the posts. Each kept post shows the number of posts (the original, plus any post carrying its tag, whether Tap made it or the owner did by hand), the people they sent, and the best network. Sorted by people, so winners rise and the rest sink.
  • "Post it again" on a kept post makes drafts in Buffer, never sent, for each connected channel it hasn't run on yet. Each draft has the same text and video, the tag, and the network's required fields. The owner reviews and sends them in Buffer. When they're sent, they appear as tiles and count toward the kept post.
  • "Forget" removes it from Tap's list and deletes the template and tag in Buffer.

Actual

Tap is up for Buffer's app form

tap.bananafest-destiny.com is live from demo/tap: a placeholder home page, /privacy (what Tap reads, writes, keeps, and how it is deleted) and a 400×400 logo. Both pages carry the pulse tag. / and /logo.png return 200; /privacy redirects to /privacy/, which returns 200. Gave the boss the values for Buffer's New Client form.

Sign in with Buffer, and the first check

The boss created the OAuth client (name Tap, confidential; account:read, posts:read, posts:write, ideas:read, ideas:write). The client id and secret are in .git-credentials and set as Worker secrets; a bogus-code call to the token endpoint gave invalid_grant, so the pair is right. Tap's Worker now has /auth/start (PKCE S256, state kept in KV for 10 minutes) and /auth/callback. The callback exchanges the code, keeps the tokens in KV under the Buffer account id, and runs one check: account, channels, sent posts, post metrics, read templates and tags, and create-then-delete one template and one tag. Buffer's auth page accepts the request (303 to its login). Waiting for the boss to sign in once.

What the sign-in showed

The boss signed in. Buffer granted account:read, posts:read, posts:write, ideas:read, ideas:write and offline_access, with a refresh token and a one-hour access token. The account has one organization and three channels (Instagram, TikTok, YouTube); five sent posts read back, each with its link. Reading templates and tags worked, and so did creating and deleting a template and a tag, so Keep this and Post it again can use real Buffer templates and tags.

Metrics did not: every post's metrics field errors with "Insufficient scope. Required: insights:read". Asking Buffer's auth page for insights:read returns invalid_scope, "requested scope is not allowed", for this client. The check's page said "no metrics, 0 of 5"; the real reason is the scope. Buffer's developer docs and changelog say nothing about third-party apps getting it; its roadmap has open requests for analytics in the API. Build step 2 (views and clicks) waits; taps are ours and need none of it.

Step 1, the tap page, is live

Signing in now leads to /me rather than the check page; the check is gone from the code, since it wrote to the account. /me reads the newest 50 sent posts from Buffer (at most every six hours), shows each one with its people and fetcher counts, and lets the owner set where each post sends people. The default is the first web address in the post's text. The bio link, /u/<name>, shows one tile per post; each tile goes through /p/<name>/<post>, which counts and then redirects. /go/<name> is the skip link. Disconnect deletes the tokens, the posts copy, the counts, the name and the sessions. Tested locally with seeded data: a browser-shaped tap counted as a person, a bare curl as a fetcher, and the skip link was counted. A javascript: destination was refused, a POST from another origin got 403, and after Disconnect the bio page 404s. Deployed; /, /privacy/, /me (302 to sign-in) and /auth/start answer as expected. The home page has the sign-in button. The privacy page now mentions the owner's one sign-in cookie, and says metrics aren't readable yet.

The boss's first look

The boss signed in and the page was built from their 50 posts, all at 0. Two faults on their screen: the "People" header wrapped onto two lines, and most thumbnails showed as broken images in their browser, though every one returned 200 to a plain fetch from here. Thumbnails now go through Tap (/t/<name>/<post>, fetched from Buffer once and cached for a day), so visitors' browsers never touch Buffer at all; all 50 return image/jpeg. The counts column no longer wraps.

Step 3: Keep this, and Post it again, are live

Built as planned. The posts copy now also holds each post's text, media URLs, tags, channel and YouTube category, plus the account's channels. Each post on /me has a "Keep this" button. Kept posts sit above the posts list, sorted by people. "Post it again" drafts for channels the post hasn't run on, and "Forget" deletes the template and tag. Results show as one line at the top of /me.

Tested live on the boss's account through a 15-minute test session, deleted afterwards. Keep this on a YouTube post made the template "YouTube, 0 people, 27 Oct" and the tag "Tap: In the middle of". Post it again made two drafts, Instagram (reel) and TikTok, with the tag and the same video, and then offered nothing more. I deleted both drafts through the API; Forget deleted the template and the tag. Nothing from the test is left in the boss's Buffer.

Drafts Tap made by hand aren't removed when the owner presses Forget; they belong to the owner. A post's sends count toward its kept post only after it is sent and shows up in Tap's copy of the posts.

  • tap.bananafest-destiny.com/make/ (signed-in owners only; linked from /me). Paste a link, and Tap reads the page: title, description, images, main text. It suggests how many videos (Comic Cover: "8 substantial points (3 with numbers) and 1 image", so 3), and the user picks 1 to 10.
  • Scripts come from gpt-5.4-mini as JSON (about 5 seconds for two). Each scene line is editable, and its image can be changed. Caps are 20 runs a day per account and 200 a day overall, until the boss sets a budget.
  • The video is rendered in the browser: 1080×1920 at 30 fps, slow zoom on the page's images with a blurred fill behind, big captions a few words at a time, and an end card with the address. WebCodecs + mp4-muxer 5.1.5. H.264 first. VP9 in MP4 is the fallback where the browser has no H.264 encoder; headless Chromium is one, so that is what was tested here: a 21.5-second video, 14 MB, in about a minute.
  • Upload goes to KV (30 days, served with ranges at /v/<id>.mp4). Drafting makes one createPost per ticked channel.
  • Live test on the boss's account: uploaded, then drafted to TikTok and YouTube. Both returned ok. Both drafts were deleted through the API, and the test video and the 15-minute session were deleted.
  • Not yet seen: an H.264 render in real Chrome, and Instagram. The privacy page now covers fetched pages, OpenAI and hosted videos. Disconnect deletes videos too.