Skip to content

Point console CTAs at the console on the current hostname (FIL-897) - #113

Merged
pyropy merged 1 commit into
mainfrom
srdjan/fil-897-host-aware-console-links
Aug 19, 2026
Merged

Point console CTAs at the console on the current hostname (FIL-897)#113
pyropy merged 1 commit into
mainfrom
srdjan/fil-897-host-aware-console-links

Conversation

@pyropy

@pyropy pyropy commented Aug 5, 2026

Copy link
Copy Markdown
Member

Every "Get started" and "Sign in" link on the site hardcoded https://app.fil.one.
The same deployment is also served from filone.ai so demos survive fil.one being
blocklisted — and on that host these CTAs sent visitors straight back to the domain
the alias exists to avoid, breaking the demo at the first click.

⚠️ Prerequisites

  1. website#112 — stacked on it; merge first.
  2. infrastructure#40 merged and appliedapp.filone.ai must resolve.
  3. fil-one#547 merged and deployed — the console must actually answer on app.filone.ai, or these CTAs point at a hostname that 403s.

Note this PR was previously closed and has been reopened. It originally targeted
filone.net, which was never registered; it now targets filone.ai.

What changes

src/lib/console-url.ts: an exact-match lookup from site hostname to console origin,
defaulting to the canonical console for fil.one and anything unrecognised.

Exact match rather than a suffix test, so filone.ai.example.com and notfilone.ai
fall back instead of being treated as the alias — covered by tests.

The remaining 45 files are the mechanical substitution of consoleUrl(),
signupUrl() and consoleUrl("/login") for the hardcoded literals. Split from
#112 so a one-line config edit isn't buried under them.

The prerendering constraint, verified rather than assumed

All 60 routes are pre-rendered at build time in a headless browser on localhost, so
the static HTML ships the canonical URL and React corrects the hrefs on hydration.
That was the main risk in this approach, so I tested it: served the real build from a
https://filone.ai origin under Playwright and checked the live DOM.

PASS  /                      host=filone.ai  alias=6  stale=0
PASS  /support               host=filone.ai  alias=2  stale=0
PASS  /lp/agents             host=filone.ai  alias=6  stale=0
PASS  /lp/migrate-from-s3    host=filone.ai  alias=5  stale=0
PASS  /pricing               host=filone.ai  alias=4  stale=0

Every checked route yields alias console hrefs and no stale ones, so the edge-redirect
fallback I'd otherwise have needed isn't required.

The value must be read from window.location and never baked in at build time — an
env var or a build-folded constant would freeze the localhost value into all 60 static
pages. Several pages call it once at module scope (const SIGNUP_URL = signupUrl()),
which is fine: module initialisation runs in the browser on the host the visitor
actually reached. The doc comment in console-url.ts records this distinction.

Deliberately unchanged

The RAG API code samples in RagPipelineProductPage keep
https://app.fil.one/api/buckets/... — that is public API reference documentation,
not site navigation, and the API is not served from the alias.

Verification

npm run typecheck clean, npm run lint 0 errors (8 pre-existing warnings in
untouched src/components/ui/*), 32 tests pass, build + 60-route prerender green,
plus the Playwright origin check above.

console-url.test.ts covers the apex, www., and all-caps forms mapping to the
alias console; the suffix attack and contains-the-alias cases falling back; path
append; and the sign-up URL on both hosts.

On a Vercel preview, click through CTAs with a filone.ai Host and confirm they land
on app.filone.ai.

Rebase note

The stack was 2 commits behind main and has been rebased. That surfaced a real
conflict: main's PR #109 moved the Barcelona pages from EUR to USD pricing, so their
imports changed under this branch. Resolved by keeping main's USD imports alongside
the new signupUrl import — verified no stale EUR symbols remain and typecheck passes.

Review remediation applied

  • The doc comment described the wrong mechanism, twice. It said pre-rendering runs "in
    a headless browser" — scripts/prerender.mjs explicitly replaced Puppeteer with jsdom
    plus renderToString — and credited React hydration with correcting the hrefs. React 18
    does not patch mismatched href attributes during hydration, so that cannot be the
    cause. The rewritten comment states only what is verified (prerendered HTML ships the
    canonical URL; the rendered DOM on the alias is correct) plus the constraint that matters
    (resolve from window at runtime, never fold in at build time) and the re-verify trigger,
    without asserting a mechanism. The Playwright check was re-run: 5 routes, alias hrefs
    everywhere, 0 stale.
  • consoleOrigin() and DEFAULT_CONSOLE_ORIGIN had no callers outside the module.
    consoleUrl() with no argument returned exactly consoleOrigin(), so the module shipped
    two spellings of one concept with the better-named one unused. FaqSection.tsx now calls
    consoleOrigin(), consoleUrl(path) takes a required path, and
    DEFAULT_CONSOLE_ORIGIN is no longer exported.
  • Two tests fixed. console-url.test.ts asserted the fallback against the imported
    constant — a tautology that could not catch a wrong value, which is the mistake worth
    catching given the cross-repo duplication. CtaSection.test.tsx still asserted the
    literal the component no longer contains, passing only because jsdom's hostname is
    localhost.
  • Cross-repo pointer added, since nothing enforces that this map agrees with
    PROD_CONSOLE_ALIAS_HOSTS in fil-one/fil-one. Converted to double quotes, matching the
    rest of the repo.
  • docs.fil.one and status.fil.one links still leave the alias. 29 of them. There is
    nothing to point them at — those subdomains do not exist on filone.ai — so this is
    recorded in the README as a known limitation rather than fixed here.

🤖 Generated with Claude Code

@vercel

vercel Bot commented Aug 5, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
fil-one Ready Ready Preview Aug 19, 2026 7:57am

Request Review

@pyropy pyropy changed the title Point console CTAs at the console on the current hostname Point console CTAs at the console on the current hostname (FIL-897) Aug 5, 2026
@pyropy pyropy closed this Aug 10, 2026
@pyropy pyropy reopened this Aug 10, 2026
@pyropy
pyropy force-pushed the srdjan/fil-897-host-aware-console-links branch from f32263f to a9b4d84 Compare August 10, 2026 17:05
@pyropy
pyropy force-pushed the srdjan/fil-897-host-aware-console-links branch from a9b4d84 to a5c994c Compare August 11, 2026 14:44
@pyropy
pyropy force-pushed the srdjan/fil-897-host-aware-console-links branch from a5c994c to 95c870e Compare August 18, 2026 09:00
@pyropy
pyropy marked this pull request as ready for review August 18, 2026 09:05
@pyropy pyropy self-assigned this Aug 18, 2026
<p>The S3-compatible API means anything built for AWS S3 works here too. Point your SDK or CLI at our endpoint and authenticate with your API keys.</p>
<p>Security comes first in the S3-compatible design: setup and migration stay simple, and buckets are private by default. Public access with full S3 parity is coming soon.</p>
<p>Read <a href="https://docs.fil.one" target="_blank" rel="noopener noreferrer" className="faq-link" onClick={() => trackDocsClick("https://docs.fil.one")}>Fil One docs</a>, <a href="https://app.fil.one" target="_blank" rel="noopener noreferrer" className="faq-link">access the app</a> to get started with no code required, or <a href="/contact-sales" className="faq-link">talk to someone on our team</a> to get started.</p>
<p>Read <a href="https://docs.fil.one" target="_blank" rel="noopener noreferrer" className="faq-link" onClick={() => trackDocsClick("https://docs.fil.one")}>Fil One docs</a>, <a href={consoleOrigin()} target="_blank" rel="noopener noreferrer" className="faq-link">access the app</a> to get started with no code required, or <a href="/contact-sales" className="faq-link">talk to someone on our team</a> to get started.</p>

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Do we need to set up an alias for the docs site too? (E.g. docs.filone.ai?)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

AFAIK we need app.filone.ai for demos only, so I would wait with that until there's a real need for it.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Updates the website’s “Start for free / Sign in / Get started” CTAs to resolve the console host at runtime from window.location.hostname, so visitors using the filone.ai demo alias are sent to app.filone.ai instead of the canonical app.fil.one.

Changes:

  • Add src/lib/console-url.ts helpers (consoleOrigin, consoleUrl, signupUrl) for hostname-aware console links.
  • Mechanically replace hardcoded https://app.fil.one/... CTA links across landing pages/components with signupUrl() / consoleUrl(...).
  • Add/adjust tests and docs to cover/describe the hostname mapping behavior.

Reviewed changes

Copilot reviewed 54 out of 54 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
src/lib/console-url.ts Adds hostname-aware console URL helpers.
src/lib/console-url.test.ts Adds unit tests for hostname → console origin mapping.
src/pages/Home.tsx Updates homepage hero CTA to use signupUrl() (and analytics destination).
src/pages/PricingPage.tsx Updates pricing CTAs to use signupUrl().
src/pages/PriceLandingPage.tsx Updates pricing LP CTAs to use signupUrl().
src/pages/StorageProductPage.tsx Switches SIGNUP_URL to signupUrl().
src/pages/StartupsLandingPage.tsx Replaces hardcoded console sign-up CTAs with signupUrl().
src/pages/WebScrapingLandingPage.tsx Replaces hardcoded console sign-up CTAs with signupUrl().
src/pages/Web3PivotLandingPage.tsx Replaces hardcoded console sign-up CTAs with signupUrl().
src/pages/Web3NativeLandingPage.tsx Replaces hardcoded console sign-up CTAs with signupUrl().
src/pages/Web3FintechLandingPage.tsx Replaces hardcoded console sign-up CTAs with signupUrl().
src/pages/VersioningLandingPage.tsx Replaces hardcoded console sign-up CTAs with signupUrl().
src/pages/RegionalCloudLandingPage.tsx Updates “Evaluate the API” CTAs to use signupUrl().
src/pages/RagStorageLandingPage.tsx Replaces hardcoded console sign-up CTAs with signupUrl().
src/pages/MultiCloudLandingPage.tsx Replaces hardcoded console sign-up CTAs with signupUrl().
src/pages/MlTrainingLandingPage.tsx Replaces hardcoded console sign-up CTAs with signupUrl().
src/pages/MigrateFromS3LandingPage.tsx Replaces hardcoded console sign-up CTAs with signupUrl().
src/pages/MetroLandingPage.tsx Replaces hardcoded console sign-up CTAs with signupUrl().
src/pages/MediaLandingPage.tsx Replaces hardcoded console sign-up CTAs with signupUrl().
src/pages/LogRetentionLandingPage.tsx Replaces hardcoded console sign-up CTAs with signupUrl().
src/pages/GrantFundedLandingPage.tsx Replaces hardcoded console sign-up CTAs with signupUrl().
src/pages/GoGlobalLandingPage.tsx Updates “Evaluate the API” CTAs to use signupUrl().
src/pages/GenomicsLandingPage.tsx Replaces hardcoded console sign-up CTAs with signupUrl().
src/pages/GamingLandingPage.tsx Replaces hardcoded console sign-up CTAs with signupUrl().
src/pages/ExitFirstLandingPage.tsx Replaces hardcoded console sign-up CTAs with signupUrl().
src/pages/EgressLandingPage.tsx Replaces hardcoded console sign-up CTAs with signupUrl().
src/pages/DigitalPreservationLandingPage.tsx Replaces hardcoded console sign-up CTAs with signupUrl().
src/pages/DataSovereigntyLandingPage.tsx Replaces hardcoded console sign-up CTAs with signupUrl().
src/pages/DataControlLandingPage.tsx Replaces hardcoded console sign-up CTAs with signupUrl().
src/pages/CostTickerLandingPage.tsx Replaces hardcoded console sign-up CTAs with signupUrl().
src/pages/ComplianceLandingPage.tsx Replaces hardcoded console sign-up CTAs with signupUrl().
src/pages/CollectionsAccessLandingPage.tsx Replaces hardcoded console sign-up CTAs with signupUrl().
src/pages/CheckpointsLandingPage.tsx Replaces hardcoded console sign-up CTAs with signupUrl().
src/pages/BarcelonaLandingPage.tsx Switches SIGNUP_URL to signupUrl().
src/pages/BarcelonaLandingPageES.tsx Switches SIGNUP_URL to signupUrl().
src/pages/BackupDrLandingPage.tsx Replaces hardcoded console sign-up CTAs with signupUrl().
src/pages/ArchivalLandingPage.tsx Replaces hardcoded console sign-up CTAs with signupUrl().
src/pages/AgentsLandingPage.tsx Replaces hardcoded console sign-up CTAs with signupUrl().
src/pages/AgentReadableLandingPage.tsx Replaces hardcoded console sign-up CTAs with signupUrl().
src/pages/AgentLoopsLandingPage.tsx Replaces hardcoded console sign-up CTAs with signupUrl().
src/pages/AgentKnowledgeLandingPage.tsx Replaces hardcoded console sign-up CTAs with signupUrl().
src/pages/AffordableLandingPage.tsx Replaces hardcoded console sign-up CTAs with signupUrl().
src/pages/solutions/Web3DappsSolutionPage.tsx Updates solution-page CTAs to use signupUrl().
src/pages/solutions/MediaArchiveSolutionPage.tsx Updates solution-page CTAs to use signupUrl().
src/pages/solutions/EnterpriseBackupSolutionPage.tsx Updates solution-page CTAs to use signupUrl().
src/pages/solutions/AiTrainingSolutionPage.tsx Updates solution-page CTAs to use signupUrl().
src/components/PlatformNavbar.tsx Updates navbar login/sign-up links to consoleUrl/signupUrl().
src/components/ProductsSection.tsx Updates product CTAs to signupUrl() (and analytics destination).
src/components/HeroSection.tsx Updates primary hero CTA to signupUrl() (and analytics destination).
src/components/CtaSection.tsx Updates CTA section button to signupUrl() (and analytics destination).
src/components/CtaSection.test.tsx Updates CTA analytics test expectations for new URL source.
src/components/ComparisonSection.tsx Updates comparison section CTAs to signupUrl().
src/components/FaqSection.tsx Updates “access the app” link to use consoleOrigin().
README.md Documents the new console-link helper usage and constraints.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +57 to +60
it("returns the bare origin when given no path", () => {
servedFrom("www.fil.one");
expect(consoleOrigin()).toBe("https://app.fil.one");
});
Comment on lines 31 to 34
label: "Start at no cost to you",
variant: "primary",
destination: "https://app.fil.one/login?screen_hint=signup",
destination: signupUrl(),
}),
Base automatically changed from srdjan/fil-897-alias-noindex to main August 18, 2026 18:14
Every "Get started" and "Sign in" link on the site hardcoded
https://app.fil.one. The same deployment is also served from filone.ai so demos
survive fil.one being blocklisted — and on that host these CTAs sent visitors
straight back to the domain the alias exists to avoid, breaking the demo at the
first click.

Adds src/lib/console-url.ts: an exact-match lookup from site hostname to console
origin, defaulting to the canonical console for fil.one and anything unrecognised.
Exact match rather than a suffix test, so filone.ai.example.com and notfilone.ai
fall back instead of being treated as the alias.

The value is resolved from window.location at runtime and must never be baked in at
build time. All 60 routes are pre-rendered by scripts/prerender.mjs, which uses
renderToString under a jsdom on localhost, so the static HTML carries the canonical
URL and the alias URLs appear only once the page renders in the browser. That the
rendered DOM ends up correct is verified rather than assumed: serving the real build
from a https://filone.ai origin yields alias console hrefs on every route checked,
none stale. It does depend on the page rendering client-side, which is why the file
records the re-verify trigger.

The remaining 45 files are the mechanical substitution of consoleUrl(),
signupUrl() and consoleOrigin() for the hardcoded literals.

Deliberately unchanged: the RAG API code samples in RagPipelineProductPage keep
https://app.fil.one/api/buckets/... — that is public API reference documentation,
not site navigation, and the API is not served from the alias. docs.fil.one and
status.fil.one links also still leave the alias; those subdomains do not exist on
filone.ai, so there is nothing to point them at. Recorded in the README.

Refs FIL-897

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@pyropy
pyropy force-pushed the srdjan/fil-897-host-aware-console-links branch from 95c870e to 4392fd7 Compare August 19, 2026 07:56
@pyropy
pyropy merged commit 8d1e808 into main Aug 19, 2026
5 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.

3 participants