Skip to content

Rebuild the landing page and build the stylesheet ahead of time - #40

Merged
botre merged 4 commits into
masterfrom
feat/landing-page-rework
Aug 8, 2026
Merged

Rebuild the landing page and build the stylesheet ahead of time#40
botre merged 4 commits into
masterfrom
feat/landing-page-rework

Conversation

@botre

@botre botre commented Aug 8, 2026

Copy link
Copy Markdown
Collaborator

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.css is generated from src/styles by the Tailwind CLI and committed, so the binary, the container and go run still 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

  • Metadata: descriptive title, canonical, full og: set, summary_large_image, and a social card drawn from the brand mark. robots.txt had Disallow: /, which would have blocked the unfurl image.
  • Accessibility: footer links went from 17-20px tall to 44px; the wordmark link no longer spans the header band; links use the design system's focus ring instead of the browser default; prefers-reduced-motion collapses all motion; selection, accent-color and color-scheme are themed.
  • Design record updated where this branch changed the behaviour it documented.
  • Em dashes removed from copy, comments and docs. The one left is the placeholder for a missing client IP, which is data rather than prose.

Verification

go vet, gofmt, go build, unit tests and prettier --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 /endpoint has 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 on master; likely the Get("/*", static.New("./public")) catch-all registered ahead of the page routes.

🤖 Generated with Claude Code

https://claude.ai/code/session_01X8JeP7AQwpd2coSfwbMopt

botre added 4 commits August 8, 2026 12:48
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
@botre
botre merged commit ed70023 into master Aug 8, 2026
3 checks passed
@botre
botre deleted the feat/landing-page-rework branch August 8, 2026 10:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant