Repository navigation
fix: every outbound link points back into the app's own router, so all 68 of them 404 - #251
Conversation
|
React Doctor found 3 new issues in 3 files · 3 warnings · score 82 / 100 (Needs work) · 4 fixed · vs 3 warnings
Reviewed by React Doctor for commit |
`chore: point this fork at its own domain` replaced six upstream hosts -- plane.so, app.plane.so, docs.plane.so, forum.plane.so, go.plane.so and developers.plane.so -- with the single host pace.yldm.ai. That host is this repo's own apps/web deployment, whose route table holds only `:workspaceSlug/...`, auth, onboarding and invitation routes, so all 68 of those links now land inside the app. Because the root route is the dynamic `:workspaceSlug` segment they do not even fail as routing 404s: `/pricing` is read as a workspace named "pricing" and fails as a missing workspace, while a deeper path like `/upgrade/pro/self-hosted` matches nothing and 404s outright. The four sites this fork does not have an equivalent of are now configuration rather than constants -- VITE_MARKETING_SITE_URL, VITE_DOCS_URL, VITE_FORUM_URL, VITE_STATUS_URL, plus VITE_TERMS_OF_SERVICE_URL and VITE_PRIVACY_POLICY_URL -- and all of them default to empty, following the call the SUPPORT_EMAIL comment beside them already made for the same reason. The rule every call site follows: when the URL is empty the control is not rendered. Not an anchor with an empty href, which navigates to the current page and reads as a broken button, and never a fallback to WEBSITE_URL, which is the mistake being fixed. WEBSITE_URL keeps its default because the app's own public home is a real destination, and the canonical and og:url metadata that points there was already correct. Three sites needed more than a guard. The product-updates footer row is now data-driven with its dot separator rendered before each surviving link rather than between fixed pairs, because the old shape would leave a dangling dot. The space app's error page picks one of four sentences depending on which contact channels exist. The admin telemetry copy loses its "in line with our Telemetry Policy" citation when there is no policy to cite, keeping the disclosure that no PII is collected. Two behaviour changes worth naming. The sign-in and sign-up screens drop the whole "you understand and agree to our Terms of Service and Privacy Policy" sentence when neither document is configured, rather than keeping the claim and dropping the links -- an installation that publishes no terms should not tell people they agreed to them. And the production error screen no longer offers a status page: pace-status.yldm.ai is NXDOMAIN, and a dead link on the screen a user reaches because something already broke is worse than nothing.
Upstream, a self-hosted installation sent buyers to the vendor's own cloud app to purchase a licence. This fork has no such service, so after the domain rename the Pro and Business "Upgrade to ..." buttons opened pace.yldm.ai/upgrade/pro/self-hosted -- a path the app does not route. Both plans have `is_active: true`, so these were live buttons, not dead code; the button's own label ("Redirecting to Stripe") describes an integration that is not here either.
`handleCheckout` becomes optional on PlanUpgradeCard and nothing passes it, so all three plans now render the existing TalkToSalesCard. PlanCheckoutButton is left in place: wiring up a real checkout is exactly what would make it reachable again. SUBSCRIPTION_REDIRECTION_URLS is gone, along with the `?? TALK_TO_SALES_URL` fallbacks that read as safety but could never fire, because that record was total over the enum.
The billing comparison's button keeps only its talk-to-sales branch, and the plan pages behind "See full features list" are omitted when no marketing site is configured.
Four of the work items seeded into every new workspace ended on a "To learn more..." paragraph pointing at /docs/core-concepts/..., which after the domain rename resolves inside the app rather than at any documentation. The seeds are embedded JSON with no interpolation anywhere in the eight files and internal/config exposes no documentation URL, so there is nothing to make these configurable through without inventing a templating pass for four sentences. Where a paragraph existed only to carry the link it goes with the horizontalRule above it, since a divider with nothing after it reads as broken; where the link sat inside a tip that teaches something, only the clause goes. Both description_html and description_stripped are edited so the plain-text mirror stays consistent, by exact substring removal rather than re-serialising, leaving formatting and escaping untouched. The //go:embed comment claimed these files are copies of upstream's, so it now records where issues.json deviates and why. The seed screenshots still load from upstream's CDN at media.docs.plane.so, which is a third-party dependency this change does not address.
18899c3 to
f6360cd
Compare
| const redirectUrl = SUBSCRIPTION_REDIRECTION_URLS[subscriptionType][frequency] ?? TALK_TO_SALES_URL; | ||
| // Open the URL in a new tab | ||
| window.open(redirectUrl, "_blank"); | ||
| window.open(TALK_TO_SALES_URL, "_blank"); |
There was a problem hiding this comment.
React Doctor · react-doctor/window-open-without-noopener (warning)
This window.open call leaves the opened page able to redirect your tab via window.opener, so pass 'noopener' in the features argument.
Fix → Pass 'noopener' in the third features argument of window.open so the opened page can't control your tab through window.opener. Add 'noreferrer' too when the destination must not receive the referrer.
Description
https://pace.yldm.ai/upgrade/pro/self-hosted?plan=month404s. So do the other 67 outbound links in the repo, for the same reason.83b5eec4 chore: point this fork at its own domainreplaced six upstream hosts with one:plane.soapp.plane.sodocs.plane.soforum.plane.sogo.plane.sodevelopers.plane.soAll of them became
pace.yldm.ai— which is this repo's ownapps/webdeployment. Its route table (apps/web/app/routes/core.ts) holds only:workspaceSlug/..., auth, onboarding and invitation routes. There is no/pricing,/docs,/forum,/upgrade,/talk-to-sales,/changelogor/legals/*.Because the root route is the dynamic
:workspaceSlugsegment, these do not even fail as clean routing 404s./pricingis read as a workspace named "pricing" and fails as a missing workspace; only a deeper path like/upgrade/pro/self-hostedmatches nothing and 404s outright. That difference is why this went unnoticed — most of the broken links look like a permissions or workspace problem rather than a bad URL.The fix is configuration, not new hardcoded URLs.
VITE_MARKETING_SITE_URL,VITE_DOCS_URL,VITE_FORUM_URL,VITE_STATUS_URL,VITE_TERMS_OF_SERVICE_URLandVITE_PRIVACY_POLICY_URLall default to empty, which is the call the comment already besideSUPPORT_EMAILinendpoints.tsmade for exactly this reason:The rule at every call site: an empty URL renders no control. Not an anchor with an empty
href— that navigates to the current page and reads as a broken button — and never a fallback toWEBSITE_URL, which is the mistake being fixed.WEBSITE_URLkeeps its default because the app's own public home is a real destination, and the canonical/og:urlmetadata pointing there was already correct.Set the env vars for whichever sites exist and the links come back with no code change.
Type of Change
Screenshots and Media (if applicable)
None. Nothing gains a visual element; several controls disappear when their destination is unconfigured, which is the point.
Test Scenarios
pnpm turbo run build check:types check:lint check:format—check:types/check:lint/check:format56/56 and every build target green. Note: the combined run failed twice onadmin#buildwithPrerender: Request failed for /: The operation was aborted due to timeout, both times while this machine was carrying an unrelated Rust build at load average ~200-300.pnpm turbo run build --filter=admin --forcepasses on its own. This is a real CI flake risk, not something this PR introduces — the admin prerender step has no timeout headroom under load, and it is worth raising separately.apps/api:go build ./...,go vet ./...,gofmt -l .clean,go test ./...0 failures (non-Docker path; the database-backed tests skip themselves by design).git grepforpace.yldm.aioutside the locale files, the threeapp/root.tsxmetadata sites,endpoints.ts,metadata.tsand the Dockerfiles returns one hit:packages/propel/.storybook/manager.tsbrandUrl, which points at the app's own home in a dev-only tool and is correct.pace.yldm.aistrings underpackages/i18n/src/locales/*/template.jsonareplaceholdervalues — example text in a URL input, not links. Untouched.Not verified, needs a browser: that each guarded control's surrounding layout still reads correctly with the control absent. The three sites where removal could leave visible debris were restructured rather than guarded (see below), but they were reasoned through, not observed.
References
Three sites needed more than a guard, and are the ones to review hardest:
product-updates/footer.tsx— the link row is now data-driven with its dot separator rendered before each surviving link instead of between fixed pairs. The original shape would leave a dangling dot whenever one link dropped out.apps/space/app/error.tsx— picks one of four sentences depending on whether an email, a forum, both or neither is configured, so the prose stays grammatical in each case.apps/admin/.../general/form.tsx— the telemetry copy loses its "in line with our Telemetry Policy" citation when there is no policy to cite, keeping the substantive disclosure that no PII is collected.Two decisions that are not mine to make and should be confirmed before merge:
VITE_TERMS_OF_SERVICE_URLandVITE_PRIVACY_POLICY_URLand the sentence returns. Worth a look from whoever owns that question.is_active: true, so those were live buttons opening a 404.handleCheckoutis now optional onPlanUpgradeCard, nothing passes it, and all three plans render the existingTalkToSalesCard.PlanCheckoutButtonis deliberately left in the tree — wiring a real checkout is what would make it reachable again.Out of scope, but found while tracing this and worse than the reported bug: the Go transactional email templates were never touched by the brand rename.
project_invitation.html,user_activation.html,user_deactivation.htmlandwebhook-deactivate.htmlstill carryx.com/planepowers,linkedin.com/company/planepowers,forum.plane.so, Plane's public roadmap atplane.sh/plane/...,github.com/makeplane/plane, prose reading "Plane is still in its early days", and a hotlinked Plane logo frommedia.docs.plane.so. These go out in real email to invited users. Fixing them needs decisions about this fork's own social accounts, so they are left alone here.Also noted: the onboarding seed screenshots still load from upstream's CDN at
media.docs.plane.so/seed_assets/*.png, a third-party dependency for content shown to every new workspace.