Skip to content

fix(home): per-request hostname for featured product; gate proto switcher#3

Merged
bschellenberger2600 merged 5 commits into
mainfrom
fix/homepage-hostname-and-proto-toggle
Apr 16, 2026
Merged

fix(home): per-request hostname for featured product; gate proto switcher#3
bschellenberger2600 merged 5 commits into
mainfrom
fix/homepage-hostname-and-proto-toggle

Conversation

@bschellenberger2600
Copy link
Copy Markdown
Member

@bschellenberger2600 bschellenberger2600 commented Apr 16, 2026

Summary

The home page was being prerendered to static HTML, so Astro.url.hostname was evaluated at build time and data-featured was always fire. That broke git-rain-first ordering (hero cards, section order, navbar link order, and logo) on git-rain marketing domains.

Changes

  • Set export const prerender = false on / so Cloudflare serves HTML with the correct data-featured for each host.
  • Match git-rain using a lowercased hostname.
  • Prototype switcher: render only in dev, on typical preview hosts (localhost, 127.*, .workers.dev, .pages.dev), or when ?proto=1. On hosts that already imply rain, the Domain row is hidden so layout switching stays without duplicating domain simulation.
  • CSS: top stripe styling for testkit/harness sections; proto bar visibility is driven by Astro instead of display: none on .proto-toggle.

How to verify

  • Deploy preview or wrangler dev after build: open / on a git-rain hostname and confirm git-rain is first (cards + nav + sections) and canonical fire domains default to git-fire first.
  • Optional: ?proto=1 on production to exercise the switcher when needed.

Note

Medium Risk
Disables prerendering for /, changing how the homepage is served/cached and making rendering depend on request hostname/query params; mistakes could cause inconsistent marketing content across domains.

Overview
Fixes homepage host-specific featured-product selection by disabling prerendering on / (export const prerender = false) and switching hostname checks to use a lowercased host (ensuring git-rain domains render with rain featured at request time).

Gates the prototype switcher so it only renders in dev/preview environments or when explicitly enabled via ?proto=1, preserves the proto flag across switcher links, and hides the Domain toggle group on git-rain hosts. Adds section accent styling for #testkit/#harness and removes the CSS-based “hide proto bar in prod” approach since visibility is now controlled server-side.

Reviewed by Cursor Bugbot for commit f8ddff1. Bugbot is set up for automated code reviews on this repo. Configure here.

Summary by CodeRabbit

  • Bug Fixes

    • Improved visibility and behavior of the proto toggle and domain subgroup based on host and query parameters; layout controls now display consistently when the proto switcher is enabled.
    • Refined auto-selection logic and added ARIA adjustments for separators to improve accessibility.
  • Style

    • Added colored top/bottom borders to testkit and harness sections; updated proto-toggle styling to rely on runtime rendering.

- Disable prerender on / so data-featured and copy match the request host.
- Use lowercase hostname for git-rain matching.
- Show prototype switcher only in dev, on preview hosts, or ?proto=1; hide
  Domain row when host already implies rain.
- Style testkit/harness section borders; remove CSS-only hide for proto bar.

Made-with: Cursor
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 16, 2026

📝 Walkthrough

Walkthrough

Added per-request rendering, case-insensitive hostname checks, request-aware proto query handling, and conditional proto-toggle UI rendering tied to environment and hostname; also added branded border styles and removed CSS-based hiding of the proto toggle.

Changes

Cohort / File(s) Summary
Page Rendering & Toggle Logic
src/pages/index.astro
Added export const prerender = false. Introduced hostLower for case-insensitive hostname checks. Added keepProtoQuery and updated protoUrl() to append proto=1 when present. Wrapped proto-toggle UI in showProtoSwitcher; added showProtoDomainGroup to hide the Domain subgroup for git-rain hosts. Adjusted separator markup to set aria-hidden="true" only in the conditional Domain+separator layout. Layout button group now always shown when proto switcher is enabled.
Styling Updates
src/styles/global.css
Added top/bottom border color rules for #testkit.section, #testkit.feature-row, #harness.section, #harness.feature-row using color-mix() with --color-testkit/--color-harness. Removed display: none from .proto-toggle (visibility now controlled by Astro logic).

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 A little toggle hops awake,

hostnames checked for every break,
proto whispers follow through the wire,
borders bloom with color, bright and dire,
requests now render fresh — a joyful quire.

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the two main changes: fixing hostname detection for the featured product and gating the proto switcher to specific contexts.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/homepage-hostname-and-proto-toggle

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@cloudflare-workers-and-pages
Copy link
Copy Markdown

cloudflare-workers-and-pages Bot commented Apr 16, 2026

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
git-fire-website f8ddff1 Commit Preview URL

Branch Preview URL
Apr 16 2026, 09:39 AM

Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: Proto switcher disappears after clicking any link
    • protoUrl now includes proto=1 when the request URL has proto=1 so switcher links keep the production opt-in.
Preview (c31e4ab13f)
diff --git a/src/pages/index.astro b/src/pages/index.astro
--- a/src/pages/index.astro
+++ b/src/pages/index.astro
@@ -1,4 +1,7 @@
 ---
+/** Per-request hostname selects featured product — must not prerender to static HTML. */
+export const prerender = false;
+
 import BaseLayout from '../layouts/BaseLayout.astro';
 import LayoutCurrent from '../components/LayoutCurrent.astro';
 import LayoutA from '../components/LayoutA.astro';
@@ -6,12 +9,26 @@
 import LayoutC from '../components/LayoutC.astro';
 
 const hostname = Astro.url.hostname;
+const hostLower = hostname.toLowerCase();
 const featuredParam = Astro.url.searchParams.get('featured');
 const layoutParam = Astro.url.searchParams.get('layout');
+const keepProtoQuery = Astro.url.searchParams.get('proto') === '1';
 
+/** Dev / preview only — hide on canonical and mirror marketing domains */
+const showProtoSwitcher =
+	import.meta.env.DEV ||
+	Astro.url.searchParams.get('proto') === '1' ||
+	hostLower === 'localhost' ||
+	hostLower.startsWith('127.') ||
+	hostLower.endsWith('.workers.dev') ||
+	hostLower.endsWith('.pages.dev');
+
+/** Hostname already selects rain; hide Domain row so the bar is not a second “tester” */
+const showProtoDomainGroup = showProtoSwitcher && !hostLower.includes('git-rain');
+
 const featured: 'fire' | 'rain' = featuredParam === 'rain' ? 'rain'
 	: featuredParam === 'fire' ? 'fire'
-	: hostname.includes('git-rain') ? 'rain'
+	: hostLower.includes('git-rain') ? 'rain'
 	: 'fire';
 
 const layout: 'current' | 'a' | 'b' | 'c' = layoutParam === 'a' ? 'a'
@@ -27,6 +44,7 @@
 
 function protoUrl(f: string, l: string): string {
 	const parts: string[] = [];
+	if (keepProtoQuery) parts.push('proto=1');
 	if (f !== 'fire') parts.push(`featured=${f}`);
 	if (l !== 'current') parts.push(`layout=${l}`);
 	return parts.length ? `?${parts.join('&')}` : '?';
@@ -39,21 +57,27 @@
 	{layout === 'c' && <LayoutC featured={featured} />}
 	{layout === 'current' && <LayoutCurrent featured={featured} />}
 
-	<div class="proto-toggle" aria-label="Prototype switcher">
-		<div class="proto-toggle__group">
-			<span class="proto-toggle__label">Domain</span>
-			<a class:list={['proto-toggle__btn', { 'proto-toggle__btn--active': featured === 'fire' }]} href={protoUrl('fire', layout)}>fire.*</a>
-			<a class:list={['proto-toggle__btn', { 'proto-toggle__btn--active': featured === 'rain' }]} href={protoUrl('rain', layout)}>rain.*</a>
+	{showProtoSwitcher && (
+		<div class="proto-toggle" aria-label="Prototype switcher">
+			{showProtoDomainGroup && (
+				<>
+					<div class="proto-toggle__group">
+						<span class="proto-toggle__label">Domain</span>
+						<a class:list={['proto-toggle__btn', { 'proto-toggle__btn--active': featured === 'fire' }]} href={protoUrl('fire', layout)}>fire.*</a>
+						<a class:list={['proto-toggle__btn', { 'proto-toggle__btn--active': featured === 'rain' }]} href={protoUrl('rain', layout)}>rain.*</a>
+					</div>
+					<div class="proto-toggle__sep" aria-hidden="true"></div>
+				</>
+			)}
+			<div class="proto-toggle__group">
+				<span class="proto-toggle__label">Layout</span>
+				<a class:list={['proto-toggle__btn', { 'proto-toggle__btn--active': layout === 'current' }]} href={protoUrl(featured, 'current')}>now</a>
+				<a class:list={['proto-toggle__btn', { 'proto-toggle__btn--active': layout === 'a' }]} href={protoUrl(featured, 'a')}>A</a>
+				<a class:list={['proto-toggle__btn', { 'proto-toggle__btn--active': layout === 'b' }]} href={protoUrl(featured, 'b')}>B</a>
+				<a class:list={['proto-toggle__btn', { 'proto-toggle__btn--active': layout === 'c' }]} href={protoUrl(featured, 'c')}>C</a>
+			</div>
 		</div>
-		<div class="proto-toggle__sep"></div>
-		<div class="proto-toggle__group">
-			<span class="proto-toggle__label">Layout</span>
-			<a class:list={['proto-toggle__btn', { 'proto-toggle__btn--active': layout === 'current' }]} href={protoUrl(featured, 'current')}>now</a>
-			<a class:list={['proto-toggle__btn', { 'proto-toggle__btn--active': layout === 'a' }]} href={protoUrl(featured, 'a')}>A</a>
-			<a class:list={['proto-toggle__btn', { 'proto-toggle__btn--active': layout === 'b' }]} href={protoUrl(featured, 'b')}>B</a>
-			<a class:list={['proto-toggle__btn', { 'proto-toggle__btn--active': layout === 'c' }]} href={protoUrl(featured, 'c')}>C</a>
-		</div>
-	</div>
+	)}
 
 	<script>
 		import { initInstallPickers } from '../scripts/install-pickers.ts';

diff --git a/src/styles/global.css b/src/styles/global.css
--- a/src/styles/global.css
+++ b/src/styles/global.css
@@ -381,6 +381,19 @@
 	scroll-margin-top: 5.5rem;
 }
 
+/* Library sections — top stripe + tinted dividers (same tokens as .site-nav a[data-project]) */
+#testkit.section,
+#testkit.feature-row {
+	border-top: 3px solid var(--color-testkit);
+	border-bottom-color: color-mix(in srgb, var(--color-testkit) 45%, var(--color-border));
+}
+
+#harness.section,
+#harness.feature-row {
+	border-top: 3px solid var(--color-harness);
+	border-bottom-color: color-mix(in srgb, var(--color-harness) 45%, var(--color-border));
+}
+
 .js [data-reveal] {
 	opacity: 0;
 	transform: translateY(14px);
@@ -804,9 +817,8 @@
 	.section--rich .wrap { grid-template-columns: 1fr; }
 }
 
-/* Prototype switcher — hidden in production; re-enable by removing display:none */
+/* Prototype switcher — only rendered on dev/preview hosts (see index.astro); opt-in with ?proto=1 */
 .proto-toggle {
-	display: none;
 	position: fixed;
 	bottom: var(--space-lg);
 	left: 50%;

You can send follow-ups to the cloud agent here.

Reviewed by Cursor Bugbot for commit 78ac614. Configure here.

Comment thread src/pages/index.astro
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/pages/index.astro`:
- Around line 58-76: The switcher links drop the ?proto=1 flag because
protoUrl(...) doesn't preserve the current query param; update protoUrl to carry
through the proto=1 flag (or accept an options param) so every generated href
includes proto=1 when the current page request/query (or the showProtoSwitcher
state) indicates proto is enabled; locate uses of protoUrl in this file (and the
protoUrl function definition) and change protoUrl to read the current query or
an explicit boolean and append ?proto=1 (or merge into existing querystring) so
the anchors rendered for featured/layout keep proto=1.
🪄 Autofix (Beta)

❌ Autofix failed (check again to retry)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 7785ae69-a939-4731-925f-2fe30a06c3ef

📥 Commits

Reviewing files that changed from the base of the PR and between 751882d and 78ac614.

📒 Files selected for processing (2)
  • src/pages/index.astro
  • src/styles/global.css

Comment thread src/pages/index.astro
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 16, 2026

Note

Autofix is a beta feature. Expect some limitations and changes as we gather feedback and continue to improve it.

Autofix skipped. No unresolved CodeRabbit review comments with fix instructions found.

Keep proto=1 on switcher links so layout/domain changes do not drop the bar.

Made-with: Cursor
…it-fire/git-fire-website into fix/homepage-hostname-and-proto-toggle

Made-with: Cursor
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/pages/index.astro (1)

13-38: ⚠️ Potential issue | 🟠 Major

Gate the query overrides, not just the switcher UI.

featured and layout still honor ?featured= / ?layout= on every request. On canonical production hosts, /?layout=a or /?featured=rain will still render prototype variants even though the switcher is hidden, and users have no visible way back. Please ignore those params unless the proto gate is enabled for the request.

🔧 Proposed fix
 const featuredParam = Astro.url.searchParams.get('featured');
 const layoutParam = Astro.url.searchParams.get('layout');
 const keepProtoQuery = Astro.url.searchParams.get('proto') === '1';

 /** Dev / preview only — hide on canonical and mirror marketing domains */
 const showProtoSwitcher =
 	import.meta.env.DEV ||
-	Astro.url.searchParams.get('proto') === '1' ||
+	keepProtoQuery ||
 	hostLower === 'localhost' ||
 	hostLower.startsWith('127.') ||
 	hostLower.endsWith('.workers.dev') ||
 	hostLower.endsWith('.pages.dev');

 /** Hostname already selects rain; hide Domain row so the bar is not a second “tester” */
 const showProtoDomainGroup = showProtoSwitcher && !hostLower.includes('git-rain');

-const featured: 'fire' | 'rain' = featuredParam === 'rain' ? 'rain'
-	: featuredParam === 'fire' ? 'fire'
+const featured: 'fire' | 'rain' = showProtoSwitcher && featuredParam === 'rain' ? 'rain'
+	: showProtoSwitcher && featuredParam === 'fire' ? 'fire'
 	: hostLower.includes('git-rain') ? 'rain'
 	: 'fire';

-const layout: 'current' | 'a' | 'b' | 'c' = layoutParam === 'a' ? 'a'
-	: layoutParam === 'b' ? 'b'
-	: layoutParam === 'c' ? 'c'
-	: layoutParam === 'current' ? 'current'
+const layout: 'current' | 'a' | 'b' | 'c' = showProtoSwitcher && layoutParam === 'a' ? 'a'
+	: showProtoSwitcher && layoutParam === 'b' ? 'b'
+	: showProtoSwitcher && layoutParam === 'c' ? 'c'
+	: showProtoSwitcher && layoutParam === 'current' ? 'current'
 	: 'b';
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/pages/index.astro` around lines 13 - 38, The query overrides for
featured/layout must be ignored unless the proto gate is enabled for the
request: update the featured and layout assignments so they only honor
featuredParam and layoutParam when showProtoSwitcher (or keepProtoQuery) is
true; otherwise derive values from hostLower/defaults as before. Concretely,
change the ternary logic in the featured (symbol: featured, uses featuredParam)
and layout (symbol: layout, uses layoutParam) initializers to first check
showProtoSwitcher || keepProtoQuery before applying the query values, falling
back to the host-based and default branches when that gate is false.
🧹 Nitpick comments (1)
src/pages/index.astro (1)

2-24: Make sure any HTML cache varies by host and proto params.

This page now renders different HTML for the same path based on hostname and query string. If Cloudflare or any upstream cache keys only on /, one variant can bleed across domains or prototype links. Please verify the cache key includes at least Host, featured, layout, and proto before enabling edge caching.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/pages/index.astro` around lines 2 - 24, This page renders different HTML
per request based on hostname and query params (see prerender=false,
hostname/hostLower, featuredParam, layoutParam, keepProtoQuery,
showProtoSwitcher), so ensure any upstream/edge cache keys vary by Host and the
featured/layout/proto query values; update the response caching policy to
include a Vary header (or edge cache key) for Host and/or include featured,
layout, proto in the cache key so variants cannot bleed across domains or proto
toggles.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@src/pages/index.astro`:
- Around line 13-38: The query overrides for featured/layout must be ignored
unless the proto gate is enabled for the request: update the featured and layout
assignments so they only honor featuredParam and layoutParam when
showProtoSwitcher (or keepProtoQuery) is true; otherwise derive values from
hostLower/defaults as before. Concretely, change the ternary logic in the
featured (symbol: featured, uses featuredParam) and layout (symbol: layout, uses
layoutParam) initializers to first check showProtoSwitcher || keepProtoQuery
before applying the query values, falling back to the host-based and default
branches when that gate is false.

---

Nitpick comments:
In `@src/pages/index.astro`:
- Around line 2-24: This page renders different HTML per request based on
hostname and query params (see prerender=false, hostname/hostLower,
featuredParam, layoutParam, keepProtoQuery, showProtoSwitcher), so ensure any
upstream/edge cache keys vary by Host and the featured/layout/proto query
values; update the response caching policy to include a Vary header (or edge
cache key) for Host and/or include featured, layout, proto in the cache key so
variants cannot bleed across domains or proto toggles.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: e3c2b6c2-6ccd-4ff3-9bff-d7461ff4151c

📥 Commits

Reviewing files that changed from the base of the PR and between 78ac614 and c31e4ab.

📒 Files selected for processing (1)
  • src/pages/index.astro

@bschellenberger2600
Copy link
Copy Markdown
Member Author

@cursor address the feedback from coderabbit

@cursor
Copy link
Copy Markdown

cursor Bot commented Apr 16, 2026

Here is what changed in response to the CodeRabbit / Bugbot thread.

Issue: On production, the bar only appears with ?proto=1, but switcher links must keep proto=1 or the bar disappears after the first click. A follow-up commit had also limited the bar to ?proto=1 everywhere, which drifted from the PR text (dev + preview hosts + ?proto=1).

Fix: Brought back the original visibility rules (import.meta.env.DEV, localhost / 127.*, .workers.dev, .pages.dev, or proto=1). protoUrl now uses URLSearchParams and only adds proto=1 when the current request already has it (protoGate), so production opt-in stays sticky without forcing proto=1 on dev/preview URLs.

const featuredParam = Astro.url.searchParams.get('featured');
const layoutParam = Astro.url.searchParams.get('layout');
const protoGate = Astro.url.searchParams.get('proto') === '1';

/** Dev / preview, or production opt-in via ?proto=1 — hide on canonical marketing domains otherwise */
const showProtoSwitcher =
	import.meta.env.DEV ||
	protoGate ||
	hostLower === 'localhost' ||
	hostLower.startsWith('127.') ||
	hostLower.endsWith('.workers.dev') ||
	hostLower.endsWith('.pages.dev');

// ...

function protoUrl(f: string, l: string): string {
	const params = new URLSearchParams();
	if (f !== 'fire') params.set('featured', f);
	if (l !== 'current') params.set('layout', l);
	if (protoGate) params.set('proto', '1');
	const qs = params.toString();
	return qs ? `?${qs}` : '?';
}

npm install and npm run build completed successfully. Changes are committed as f8ddff1, pushed to fix/homepage-hostname-and-proto-toggle, and PR #3 was updated against main.

Open in Web Open in Cursor 

CodeRabbit asked to carry proto=1 through protoUrl for production ?proto=1.
Use URLSearchParams and only append proto when the request opted in.

Re-show the switcher on localhost, 127.*, and Cloudflare preview hosts per
the PR description, while still hiding it on canonical marketing domains.

Co-authored-by: Ben Schellenberger <bschellenberger2600@users.noreply.github.com>
@bschellenberger2600 bschellenberger2600 merged commit c2e4d20 into main Apr 16, 2026
4 checks passed
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.

2 participants