Skip to content

feat(home): add hosted-demo 'try in browser' entry; rename primary CTA to Install Freenet - #68

Merged
sanity merged 6 commits into
mainfrom
feat/try-freenet-discoverability
Jul 7, 2026
Merged

feat(home): add hosted-demo 'try in browser' entry; rename primary CTA to Install Freenet#68
sanity merged 6 commits into
mainfrom
feat/try-freenet-discoverability

Conversation

@sanity

@sanity sanity commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

DRAFT — held for review, not to be merged until the copy/framing is signed off (merging auto-deploys freenet.org).

Problem

try.freenet.org lets someone try Freenet in-browser with zero install, but it is not linked anywhere on freenet.org, so nobody discovers it. Meanwhile the primary hero CTA is labeled "Try Freenet" but actually leads to the install flow (/quickstart/), so the word "try" is spent on install.

Approach

Surface the hosted demo as a secondary, clearly-labeled entry while keeping the self-hosted path primary (deliberate: the hosted demo is centralized, which is the opposite of the point of Freenet, so it must stay a taste, not the destination).

  • Primary CTA renamed Try Freenet -> Install Freenet (accurate: it leads to install/quickstart).
  • New secondary line under it links to https://try.freenet.org, styled subordinate to the primary button.
  • The note frames the demo honestly as temporary and centralized ("runs on our server, not the network") with a visible path home ("run your own peer ... bring your data along in one click" — the one-click migration from freenet-core #4592).

Anti-funnel framing

The whole point is discoverability without funneling people onto the centralized gateway forever. The subline does that work, and the one-click data migration means graduating to your own peer costs you nothing.

Open question (for review)

Installing is a means to an end — you install Freenet to reach decentralized apps, not as an end in itself. Worth deciding whether the hero should lead with "what you can do" and treat install + try-in-browser as two doors in. This PR is the incremental version to react to first.

Testing

Rendered locally with hugo server; verified desktop + mobile layout. No functional/JS/WASM changes — copy + CSS only.

[AI-assisted - Claude]

🤖 Generated with Claude Code

https://claude.ai/code/session_012jmCd1tvDH1EsVTtaDVnxJ

sanity and others added 6 commits July 7, 2026 08:22
…A to Install Freenet

Surface try.freenet.org on the homepage as a low-friction, no-install way to
try Freenet, while keeping the self-hosted path primary. The hosted demo is
framed honestly as temporary and centralized ('runs on our server, not the
network') with a visible path home ('run your own peer ... bring your data
along in one click', the one-click migration from freenet-core #4592).

- Primary CTA renamed 'Try Freenet' -> 'Install Freenet' (more accurate: it
  leads to the install/quickstart flow).
- New secondary entry links to https://try.freenet.org, styled subordinate to
  the primary button so the real (decentralized) path stays front and center.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012jmCd1tvDH1EsVTtaDVnxJ
…nted invite

The homepage 'try in browser' entry now points to a small /try/ page that mints
a real River invite (same ghostkey /create-invite API as quickstart) and opens
the Freenet Official room on try.freenet.org — the most compelling first-run
demo — instead of a static link that would land users un-joined.

- Parameterize river-invite-button with base= (default: local peer :7509 for
  quickstart) + hosted= (swaps the 'make sure Freenet is running' note for a
  hosted-demo note). Base is read from a data attribute to avoid JS-context
  escaping. Quickstart behavior is unchanged.
- New /try/ page: honest hosted-demo framing (centralized, temporary) with a
  clear path to install your own peer.
- Hero secondary link now targets /try/ (was a static try.freenet.org link).
- Fix stale quickstart copy: invite limit is 20/day per IP, not 5 (matches the
  API in rust/api/src/routes.rs).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012jmCd1tvDH1EsVTtaDVnxJ
Address mechanism-focused button copy: 'Get Invite Code' -> 'Join the Freenet
chat room' (experience, not plumbing). On the hosted demo (/try/) the button
now joins in ONE click: it mints the invite in the background and navigates
straight into River, instead of the two-step get-invite-then-open flow.

- Add cta= (button label) + one-click behavior gated on hosted=. Quickstart is
  unchanged behaviorally: still two-step (opens the local peer in a new tab,
  still shows the raw code for riverctl users).
- Relabel widget intro 'Get your invite to' -> 'Join'; quickstart 'get an invite
  to' -> 'join the' room.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012jmCd1tvDH1EsVTtaDVnxJ
Even vertical gaps made it unclear what grouped with what: the Install button
floated between the paragraph and the try-link, and the hero didn't visually
close before the next section. Tighten within groups, widen between them:

- Headline hugs its paragraph (pitch reads as one unit).
- Button + try-in-browser link + note sit tight together (one action group),
  with a clear gap above (from the pitch) and a bigger gap below (hero closes).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012jmCd1tvDH1EsVTtaDVnxJ
The one-click try flow mints a River invite via gkapi.freenet.org before
navigating; measured at ~0.6s, which is DNS+TCP+TLS connection setup (the
handler itself is a rate-limit check + ed25519 sign, single-digit ms), not slow
code. Preconnect warms that connection while the user reads the page, so the
mint on click skips setup. Emitted prod-only on the pages that call gkapi
(/try/, /quickstart/, /donate/); the fetch is same-top-level-site as the page,
so the warmed connection is actually reused (unlike cross-origin pre-warming of
try.freenet.org, which browser partitioning defeats).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012jmCd1tvDH1EsVTtaDVnxJ
From the pre-merge review of #68:
- Add dark-mode color overrides for the new .cta-secondary / .cta-note (they
  were dim / below AA contrast on the dark hero, inconsistent with every other
  link); match the site's existing #4da6ff / #94a3b8 dark values.
- Soften 'bring your data along in one click' -> 'keep using the same rooms on
  the real network'. The one-click hosted->local migration (#4592) is deployed
  but only mechanism-verified with an empty token, not a data-bearing River
  user; use a claim that's true today (rooms are on-network contracts). Restore
  the stronger wording once #4592 is tested end-to-end with real data.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012jmCd1tvDH1EsVTtaDVnxJ
@sanity
sanity marked this pull request as ready for review July 7, 2026 18:39
@sanity
sanity merged commit 1b73a0a into main Jul 7, 2026
3 checks passed
@sanity
sanity deleted the feat/try-freenet-discoverability branch July 7, 2026 18:39
sanity added a commit that referenced this pull request Aug 9, 2026
* docs(quickstart): stop competing with /try/, and link to it

/quickstart/ was titled "Try Freenet: Join River", which collided with
/try/ ("Try Freenet in your browser"). The two were near-indistinguishable
in a tab strip or a search result, while the nav called the page a third
thing, "Quickstart".

The collision is a leftover of one-directional editing. /quickstart/ got
that title on 2026-05-04 (7e3cb08), two months before /try/ existed. The
/try/ work on 2026-07-07 (#68/#69/#70) added the new page and rewired the
homepage, but never came back to the older one.

The link was one-way for the same reason: /try/ pointed at /quickstart/
twice, /quickstart/ pointed at /try/ not at all. So anyone arriving from
the nav, a search result, /apps/, /river/ or the manual never learned the
no-install option existed, which is the direction that matters more since
the install page is the one carrying the friction.

- Title and <title> become "Install Freenet: Join River", matching the
  homepage's primary CTA and freeing "Try Freenet" for /try/. The URL is
  unchanged, so no redirects.
- A pointer to /try/ sits above Step 1, before the install friction rather
  than buried in "What's Next?", and describes the demo the way /try/
  describes itself ("hosted demo", runs on our server, a preview).

Both pages now name each other in the other's own vocabulary: /quickstart/
links "Try River in your browser", /try/ links "Install Freenet →".

Verified with cargo make check-links (self-test plus 222 pages, no broken
references) and by screenshotting both pages at 1280px and 390px.

[AI-assisted - Claude]

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KBzsn4BUH4dHQ9gMHSGj2P

* docs(quickstart): fix an inaccurate claim about the hosted demo

Review found the new paragraph described /try/ as running "on our server
rather than peer-to-peer". That is wrong, and it made /quickstart/ claim
more centralization than /try/ claims for itself.

try.freenet.org is a Freenet peer we run, not a non-P2P reimplementation.
It serves the same node-gateway path shape a local peer serves, for the
same contract key: /v1/contract/web/raAqMhMG7KUpXBU2SxgCQ3Vh4PYjttxdSWd9ftV7RLv/
against try.freenet.org, versus localhost:7509 for an installed peer (the
default base in themes/freenet/layouts/shortcodes/river-invite-button.html).
What is centralized is whose peer holds your session, not whether the
network is involved. Reworded to say that, matching how /try/ puts it
("your data lives with us").

Two more review findings:

- "fastest way to see the network in action" was contradicted one
  paragraph later by a no-download option. Now "best way".
- Troubleshooting's network-requirements note was a dead end for exactly
  the reader /try/ serves: someone whose firewall blocks UDP hole
  punching, who has already tried to install and failed. It now points
  there, since the browser demo reaches the network over HTTPS.

Not adopted: propagating /try/'s "export your data in one click" claim to
this page. The reviewer flagged it as unverified and I did not verify it,
so it stays on the one page that already asserts it.

Verified again with a clean build: check-links self-test passes, no broken
internal links across 222 pages.

[AI-assisted - Claude]

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KBzsn4BUH4dHQ9gMHSGj2P

* docs(quickstart): balance the hosted-demo caveats

Second review pass. Three copy findings, all in the text this PR added:

- "your data lives with us" carried the alarming half of /try/'s framing
  without the mitigation that follows it there ("encrypted with your access
  key, so while you're not using it even we can't read it"). A reader who
  never clicks through got only the scary part. Dropped rather than
  duplicated: "a preview rather than the real thing" already states the
  tradeoff, and /try/ carries the full data story where the reader actually
  decides to use it.

- The firewall note promised the demo "still works", unconditional. The
  transport claim holds for the parts this repo can show (the page and the
  invite API are both HTTPS/443), but River in the browser also needs a
  WebSocket to the hosted node, which lives in another repo and was not
  verified, and a DPI proxy can block WS upgrades while allowing HTTPS. Now
  "usually still works", and says "over HTTPS" so the reason is legible.

- That same sentence called it "River in your browser" with no indication it
  is hosted. Someone deep-linking to #troubleshooting from a search would
  read it as the real thing. Now "the hosted demo".

- "best way to see the network in action" was still an unsupported
  superlative sitting above a paragraph that offers a different path first.
  Now "for real", which is the distinction that actually holds.

Clean rebuild: check-links self-test passes, no broken internal links across
222 pages, and both /try/ links plus the new wording confirmed present in the
built HTML. Re-screenshotted at 1280px.

[AI-assisted - Claude]

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KBzsn4BUH4dHQ9gMHSGj2P

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
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