Rebuild the landing page and build the stylesheet ahead of time - #40
Merged
Conversation
Every page compiled its CSS in the browser through the Tailwind Play CDN, which Tailwind documents as development-only. It was the one render-blocking resource on every page, it came from a third party, and a slow CDN left the site with no layout at all. public/app.css is now generated from src/styles by the Tailwind CLI and committed, so the binary, the container and `go run` still need no Node. CI rebuilds it and fails if the committed file has drifted, which is the only thing keeping a generated artifact honest. The source is split by responsibility: an entry that only imports, element defaults and reclaimed browser surfaces, the two component patterns utilities cannot express, and the keyframes with their reduced-motion contract. Prettier ignores the generated sheet. Left alone it would reformat the minified output, the next build would revert it, and the freshness check could never pass. Claude-Session: https://claude.ai/code/session_01X8JeP7AQwpd2coSfwbMopt
The layout loaded the syntax highlighter, Alpine and the three endpoint scripts on every page. The marketing and contact pages use none of them and now ship no JavaScript at all; the endpoint page opts in through a render flag. The styles those scripts used to inject at startup moved into the stylesheet, so they apply before first paint instead of after. Pages also carry the metadata their two arrival paths need. The title was the bare product name and there were no Open Graph tags, so a search result showed one word and a pasted link unfurled as a naked URL. The social card is drawn from the brand mark and renders an example capture, and robots.txt now allows the assets an unfurl has to fetch. Absolute URLs track the requesting host rather than a configured hostname, so a self-hosted deployment advertises itself. Claude-Session: https://claude.ai/code/session_01X8JeP7AQwpd2coSfwbMopt
The page described a live stream of HTTP requests and demonstrated none of it, then asked for a click. It now renders one example capture from the same components the endpoint page uses: a method badge, a path, real headers and a pretty-printed body, labelled as an example. It also states what it is asking for. No account, free forever, four-hour retention and a URL anyone holding it can read are the facts a visitor needs before pointing live traffic at it, and they now sit with the button instead of appearing after the click or nowhere. Six use-case cards became three: half of them were one activity in three costumes. The cards no longer lift on hover, because nothing there is clickable and a surface that responds to the cursor promises otherwise. The section heading is a heading rather than an uppercase label. Footer links carry a target big enough to hit on a phone, the wordmark link no longer spans the whole header band, and links use the design system's focus ring rather than the browser default. Claude-Session: https://claude.ai/code/session_01X8JeP7AQwpd2coSfwbMopt
The design record described behaviour this branch changed: cards that lift on hover, a stylesheet compiled in the browser, and links with no authored focus style. It now also covers the browser surfaces the base layer reclaims and the reduced-motion contract. Prose across the records and the shipped copy no longer uses em dashes. Clauses are rewritten rather than having the character swapped for a hyphen. The one remaining em dash is the placeholder for a missing client IP, which is data rather than prose. Claude-Session: https://claude.ai/code/session_01X8JeP7AQwpd2coSfwbMopt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Acts on the critique of the landing page. Two problems drove most of it: the page described a live stream of HTTP requests without showing one, and every page compiled its CSS in the browser.
The page now shows the product
One example capture sits under the CTA, rendered from the same components the endpoint page uses: a method badge, a path, real headers, a pretty-printed body. Static markup, labelled as an example, fabricating nothing.
It also states what it asks for. No account, no email, free forever. Requests are deleted after 4 hours, and anyone with the URL can read them. Those facts previously appeared after the click (retention) or nowhere at all (no auth), which meant the page borrowed the visitor's trust and settled up later.
Six use-case cards became three, since half were one activity in three costumes. They no longer lift on hover: nothing there is clickable, and a surface that responds to the cursor promises otherwise.
The stylesheet is built, not compiled in the browser
public/app.cssis generated fromsrc/stylesby the Tailwind CLI and committed, so the binary, the container andgo runstill need no Node. The Play CDN it replaces is documented by Tailwind as development-only, was render-blocking, was third-party, and left the site with no layout at all if jsDelivr was slow.The landing page went from 10 requests across 3 origins to 4 across 1, and ships zero JavaScript. The highlighter, Alpine and the endpoint scripts now load only where they are used.
CI rebuilds the sheet and fails if the committed file drifted. Prettier ignores it, because otherwise it would reformat the minified output, the next build would revert it, and the freshness check could never pass.
Also
og:set,summary_large_image, and a social card drawn from the brand mark.robots.txthadDisallow: /, which would have blocked the unfurl image.prefers-reduced-motioncollapses all motion; selection,accent-colorandcolor-schemeare themed.Verification
go vet,gofmt,go build, unit tests andprettier --check .clean. Playwright 37/37, including three new assertions: the capture renders, and the landing page ships no scripts. Two existing assertions were updated because they encoded copy this branch intentionally changed.Mobile and desktop checked in a browser at both breakpoints.
Not addressed
Still open from the same review, both backend and out of scope here:
POST /endpointhas no CSRF protection, so any cross-origin form post can mint an endpoint./ships with no security headers at all, while every other route has them. Reproduces onmaster; likely theGet("/*", static.New("./public"))catch-all registered ahead of the page routes.🤖 Generated with Claude Code
https://claude.ai/code/session_01X8JeP7AQwpd2coSfwbMopt