# 03 ยท The site, through beehiiv's MCP *From Adam Schoenfeld (adamgtm.com). Part of a kit for beehiiv builders at https://adamgtm.com/design-process/. True as of October 23, 2026. beehiiv ships often; when a tool's own description disagrees with this file, trust the tool and test.* posts.adamgtm.com runs on beehiiv's **advanced builder**. beehiiv also has a simpler website builder made of presets, where you can only override copy, images and links. The MCP tools tell you which one a site is. Everything below is about the advanced builder. My agents built it through the MCP from Claude Code. The scroll popup's design and a few live-only switches were done in beehiiv's website builder (gotchas 2 and 15). What I changed: the header (now the same as adamgtm.com, to the pixel on desktop), a phone header, the home page, the archive, a tag page, the post page (a signup in the byline row, a "Hi, I'm Adam" card at the end, "Keep reading"), the theme, the signup and login modals, the footer, and the scroll popup. ## What works - **Read the rulebook first.** `learn_site_design` and `learn_page_authoring` explain the node types, the builders and the design rules a save is checked against. Then read what's there: `get_site`, `get_site_global`, `get_page_content`. - **Small, targeted edits.** `save_page_content` takes either a whole-page `design` or `operations` against nodes you read (`set_attrs`, `replace`, `insert_before`, `insert_after`, `delete`). Use operations. A save is charged only for the rule violations it adds, so a one-attribute change passes on a page that already breaks rules, while a full redesign has to satisfy all of them. - **The right tool for each layer:** `save_site_theme` for tokens (colors, fonts, borders), `save_site_global` for the navbar, footer and the login and signup modals, `save_page_content` for page bodies, `edit_post` for post metadata (tags, authors, thumbnail). - **Custom HTML blocks** (`embed`) for what the blocks can't do. Mine hold small scoped CSS, the numbered tiles and logo wall on the home page, the phone tab strip and the footer. - **Content tags make sections.** One "Monthly report" tag gave me a home section, an archive filter and a tag page at `/t/monthly-report`. - **Rollback points before the first write.** List the site and page versions (`list_site_versions`, `list_page_versions`) and write down the ids. `restore_version` takes a site version (globals, theme, modals and the pages it covers) or a page version (one page's body). Post metadata isn't versioned; note the old values yourself. - **Preview the draft before publishing.** `get_page` returns a draft preview URL. Open it once in the browser your agent drives: it sets a cookie, and from then on your live domain renders the draft site. Hide the "Draft Preview" bar (the first child of ``) before you measure, and don't share the URL. After publishing, check the live site in a new browser context without that cookie, or you'll still be looking at the draft. - **Measure against your main site.** My header matches adamgtm.com within 0.1px on every edge at 1440 and 1000px wide. Measure edges in the browser; don't compare screenshots by eye. ## Gotchas: what happened, what to do ### Draft and publish 1. **MCP edits land in the draft. A human publishes.** **What happened:** every write to pages, the theme, the navbar, the footer and the modals went to the draft; none of it was live until I published in beehiiv's website builder. Gotchas 2 and 3 are the exceptions. **What to do:** build and check everything in the draft, then hand over a list of what's pending. Publish all pages: I never confirmed whether publishing one page also promotes the theme, modals and navbar. 2. **Some page settings write live, not draft.** **What happened:** `edit_page` changes the page record directly. My agent switched the home page's footer on to test it, and it showed on the live old home page within seconds. It switched it back about 18 seconds later. **What to do:** treat `edit_page` as live. Leave settings like `show_footer` for the human to flip at publish time. 3. **Post metadata on published posts goes live.** **What happened:** tags, authors and thumbnails set with `edit_post` showed on the live site without a publish (the home feed caught up after its cache). **What to do:** get the human's OK before touching a published post, and record the old values first. 4. **Saving the theme can reset navbar colors.** **What happened:** one `save_site_theme` call (background and border colors only) cascaded into the draft: the navbar's link and brand colors went to the theme default, the footer and modals took the new tokens, and every page background changed. **What to do:** do theme changes first. Then check every global and restore what moved. On items you color by hand, turn off theme token binding so the next theme save leaves them alone. 5. **Cached pages lag behind changes.** **What happened:** after a change went live, beehiiv's CDN kept serving copies of two posts cached before it (their cache header allowed up to 30 days). Those copies still had the old settings. **What to do:** check each change on a fresh load of several posts, not one. In my case a per-post edit refreshed that post's cached copy within minutes; the other post caught up on its own. ### Header and navigation 6. **The mobile navbar holds one menu.** **What happened:** the navbar has independent desktop and mobile trees. The desktop tree can take a second row; the mobile tree can't, and a second mobile menu is refused. My site's phone header has two rows (name and button, then the three sections as tabs). **What to do:** keep the navbar to one row on phones and add the second row as a phone-only HTML embed at the top of each page. 7. **What happened:** a navbar `link` item ignores background and border colors. **What to do:** make it `type: "button"` with `onClick: "link"` and an `href`, and it takes a fill. 8. **What happened:** the subscribe control was refused on save. **What to do:** it needs `action: "sign_up"` and `onClick: "action"` together. 9. **What happened:** the phone menu panel was see-through. **What to do:** set `navbar_menu_burger.contentBackgroundColor`. 10. **What happened:** the desktop tree applies above 768px, and there's no breakpoint in between. Just above 768px my full desktop bar runs up to 50px too wide. **What to do:** keep the desktop bar short enough for about 770px, or accept the gap. 11. **What happened:** the rulebook refused a navbar link to `/archive` labeled "Newsletter". **What to do:** a link to `/archive` must say "Archive". Point "Newsletter" at the home page. ### The post page 12. **A signup form inside the post header renders as a non-working copy.** **What happened:** I put the signup in the byline row, inside `postHeader`. beehiiv renders signups inside the post header (and other card templates) as a static copy: `pointer-events-none`, no form, no submit. It looked perfect in screenshots. A reader couldn't click it. **What to do:** put the real signup as a top-level node in the reading section, right after the header, and move it into the byline row with page CSS. Test every form by clicking and typing in it. 13. **Post body type comes from the email theme.** **What happened:** the web body uses each post's email theme (my old one: Helvetica 16px, italic navy links). The site sets only text color, link color and the reading width on `postContent`, and the rulebook requires all three. **What to do:** set those three on the site. To change the font or size, change the email template's theme, and send a test email first, because it changes the email too. 14. **Fixing the post body's padding.** **What happened:** beehiiv pads every email block 15px on each side, so on the web the body sat inset from the title and byline row. I noticed the byline row looked wider than the post. **What to do:** cancel that padding on the web with a scoped style rule in an HTML block on the post template, then measure that the body's left and right edges match the header's. 15. **The scroll popup needs a per-post switch.** **What happened:** the popup's design lives in the post page's document settings, which the MCP can't write, so its design is built in beehiiv's builder (Post page, Layers, Popups, Email Capture). Switching it on is a publication setting, live on every post at once. Each post also has its own setting (`email_capture_type_override`: none, gated or popup) that beats the default. After I switched the popup on, two posts' cached copies still had it off. Setting one post's override to "popup" refreshed its copy in about two minutes; the other refreshed on its own. The API can't set a post back to "follow the default" afterward. **What to do:** after switching it on, load your top posts fresh, scroll past halfway and confirm the popup opens. Use the per-post switch only where you need it, knowing it sticks. 16. **What happened:** beehiiv adds a sticky back, heart and share bar to posts; the heart showed zero likes. Its switch lives with the popup, in the builder only. **What to do:** switch it off in the builder (Post page, Layers, Post actions), or hide it with a scoped style rule. 17. **What happened:** some post page nodes can't be removed. `postComments` stays even with comments off. `recommendedPosts` can't be deleted or swapped. **What to do:** leave `postComments` (it renders nothing with comments off). Use `recommendedPosts` as a container: it can hold a heading, an end card and any post feed. 18. **What happened:** a `latest` feed leaves out the post you're reading, so "latest 3" showed two on the newest posts. **What to do:** ask for 4 and hide the fourth with CSS. 19. **What happened:** posts with no author attached showed an empty byline. **What to do:** attach authors with `edit_post` (`user_ids`). Check older posts too. 20. **What happened:** my email carries its own H1 because the email hides beehiiv's title, so on the web the title showed twice. **What to do:** hide the in-body H1 on the web with a scoped style rule. ### Home and archive 21. **What happened:** the home page has required parts: an H1 bound to the publication name, the publication description, a signup (warned if it's not in the hero), a featured feed and an archive feed, and sections anchored `featured-posts` and `archive-posts`. **What to do:** keep them when you redesign. Small operations pass on a page that lacks some; a whole-page design must have all. 22. **What happened:** archive search and the tag filter work only on the first archive feed on a page. My archive has two feeds with a band between them. **What to do:** while someone searches or filters, hide the band and the second feed with scoped CSS. 23. **What happened:** only `archive` feeds take an offset, and an archive feed draws a "Load more" link. **What to do:** use an archive feed with an offset for "the rest after the first six", and hide its Load more where you don't want it. 24. **What happened:** card rules bit. A card image needs `aspectRatio` and `objectFit`, or heights go ragged. Repeating a merge tag in one card renders nothing. Absolute positioning doesn't survive inside a card. One hover effect per feed. **What to do:** set the image ratio to your thumbnail's own (see `04-thumbnails-and-checks.md`) and keep cards simple. 25. **What happened:** containers without a `backgroundColor` got painted the theme color. On phones, children inherited a parent's border, and text got 4px of extra padding. **What to do:** give every container a background. Set `mobileBorderStyle`, `mobileBorderWidth` and `mobilePadding` where you care. The rulebook also wants a `mobileFontSize` on display text of 44px and up. 26. **What happened:** there's no merge tag for the subscriber count, so my old home page showed a hand-typed count that had gone stale. **What to do:** use a rounded floor with a plus sign, which stays true as the list grows, or no number. ### HTML blocks and CSS 27. **What happened:** scoped CSS in an HTML block works. Global resets and `position: fixed` don't. The editor caps a block at 50,000 characters, and scripts run only in the preview and on the live site, not in the editor. **What to do:** keep CSS small and scoped. Don't build sticky bars. 28. **What happened:** my style rules target beehiiv's own markup in a few places (the share buttons, the Load more link, the sticky bar's form), which a beehiiv release can change. **What to do:** scope every rule to a section anchor or to beehiiv's markup, so a selector that stops matching leaves plain beehiiv behind instead of a broken page. Keep a list of every rule and the block it lives in. 29. **What happened:** signup forms use the publication's default signup flow (mine sends new subscribers on to my main site) unless you set another. **What to do:** decide where each form should land before launch, and test one real signup.