Add canonical public launch status route
This commit is contained in:
parent
0505a49a42
commit
d5f800de65
15 changed files with 339 additions and 83 deletions
|
|
@ -243,6 +243,7 @@ The website now includes:
|
|||
|
||||
- public download center
|
||||
- dedicated public `/getting-started` route for the shortest browser-to-desktop onboarding path
|
||||
- dedicated public `/launch-status` route for the canonical preview-versus-launch rollout checklist
|
||||
- plan-gated release posture
|
||||
- browser-to-desktop token handoff
|
||||
- protected-dashboard download gating above the public target-description page
|
||||
|
|
|
|||
|
|
@ -73,6 +73,16 @@ route now acts as the canonical public onboarding/manual surface for:
|
|||
- first launch and higher-dimensional verification order
|
||||
- explicit XR/controller boundary truth
|
||||
|
||||
The next same-family launch-authority continuation then added a dedicated
|
||||
public `/launch-status` route so the current preview-versus-launch posture no
|
||||
longer has to be reconstructed from pricing plus compact public banners alone.
|
||||
That route now acts as the canonical public authority surface for:
|
||||
|
||||
- the current launch-readiness checklist
|
||||
- rollout hardening tracks
|
||||
- packaged desktop proof in launch context
|
||||
- release-reference and support follow-through
|
||||
|
||||
## Protected-surface continuation
|
||||
|
||||
The protected browser shell is no longer only one strong dashboard route plus
|
||||
|
|
@ -109,6 +119,7 @@ drop in information quality.
|
|||
- pricing page
|
||||
- download page
|
||||
- getting-started page
|
||||
- launch-status page
|
||||
- support page
|
||||
- changelog page
|
||||
- open-source notices page
|
||||
|
|
|
|||
|
|
@ -1049,6 +1049,10 @@ Current audit note:
|
|||
browser-to-desktop onboarding/manual path is available as one canonical
|
||||
crawlable page rather than only as repeated fragments across homepage, docs,
|
||||
and download
|
||||
- the next same-family launch-authority continuation then did the same for
|
||||
preview-versus-launch posture through a dedicated public `/launch-status`
|
||||
route, so rollout blockers, release references, support lanes, and packaged
|
||||
proof no longer have to be reconstructed from pricing plus scattered callouts
|
||||
- this keeps the public manual professional without inventing browser
|
||||
simulator parity or widening the native XR branch
|
||||
- focused validation for that continuation stayed green under:
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -4,6 +4,7 @@ First-party `hypertwist.app` surface for HyperTwist:
|
|||
|
||||
- public homepage, about, resources, pricing, support, and legal pages
|
||||
- dedicated public `/getting-started` onboarding route for the first real browser-to-desktop operator journey
|
||||
- dedicated public `/launch-status` route for the canonical preview-versus-launch rollout checklist
|
||||
- public feature-atlas route for current capability and boundary truth
|
||||
- browser-facing operator/account dashboard
|
||||
- protected browser-access, account, and notices routes backed by live auth-health and release-manifest authority
|
||||
|
|
@ -80,6 +81,9 @@ manual:
|
|||
- that same first-session story is now also anchored at a dedicated public
|
||||
`/getting-started` route so the shortest complete onboarding/manual lane is
|
||||
crawlable, canonical, and easier to hand off than the broader page set alone
|
||||
- the same launch-authority story is now also anchored at a dedicated public
|
||||
`/launch-status` route so preview-versus-launch truth, rollout blockers,
|
||||
packaged proof, and release references have one canonical authority surface
|
||||
- the protected app shell now also carries richer operator-facing browser
|
||||
boundary, account, entitlement, and notices guidance instead of treating
|
||||
those routes as thin placeholders beside the main dashboard
|
||||
|
|
|
|||
|
|
@ -15,6 +15,9 @@
|
|||
<url>
|
||||
<loc>https://hypertwist.app/getting-started</loc>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://hypertwist.app/launch-status</loc>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://hypertwist.app/docs</loc>
|
||||
</url>
|
||||
|
|
|
|||
|
|
@ -187,6 +187,14 @@ describe('AppRouteTree', () => {
|
|||
expect(await screen.findByText('Start in the browser. Train in the desktop runtime.')).toBeTruthy()
|
||||
})
|
||||
|
||||
it('renders the launch-status page through the real public route tree', async () => {
|
||||
renderRoute('/launch-status')
|
||||
expect(screen.getByText('Launch status')).toBeTruthy()
|
||||
expect(screen.getByText('Launch authority')).toBeTruthy()
|
||||
expect(screen.getByText(/canonical public launch-readiness checklist, release posture, and preview-versus-launch authority map/i)).toBeTruthy()
|
||||
expect(await screen.findByText('See exactly what still separates preview from public launch.')).toBeTruthy()
|
||||
})
|
||||
|
||||
it('renders the login page through the real public route tree', async () => {
|
||||
renderRoute('/login?next=%2Fapp%2Fdownloads')
|
||||
|
||||
|
|
|
|||
|
|
@ -120,6 +120,7 @@ import {
|
|||
FeaturesPage,
|
||||
GettingStartedPage,
|
||||
HomeLanding,
|
||||
LaunchStatusPage,
|
||||
OpenSourceNoticesPage,
|
||||
PricingPage,
|
||||
PrivacyPage,
|
||||
|
|
@ -1422,6 +1423,117 @@ describe('public marketing pages', () => {
|
|||
expect(document.head.querySelector('meta[property="og:url"]')?.getAttribute('content')).toBe('https://hypertwist.app/getting-started')
|
||||
})
|
||||
|
||||
it('renders the dedicated launch-status page as the canonical public release-readiness route', async () => {
|
||||
mockGetAuthHealth.mockResolvedValue({
|
||||
ok: true,
|
||||
service: 'hypertwist-auth-server',
|
||||
supertokens: {
|
||||
configured: true,
|
||||
reachable: true,
|
||||
ready: true,
|
||||
apiVersion: '5.4',
|
||||
error: null,
|
||||
oauth: {
|
||||
github: true,
|
||||
google: false,
|
||||
},
|
||||
},
|
||||
fallback: {
|
||||
enabled: true,
|
||||
active: false,
|
||||
reason: null,
|
||||
},
|
||||
billing: {
|
||||
statePath: '/var/lib/hypertwist/auth/hypertwist-billing-state.json',
|
||||
processedEventCount: 0,
|
||||
pricePlanMapConfigured: false,
|
||||
productPlanMapConfigured: false,
|
||||
webhookSecretConfigured: false,
|
||||
},
|
||||
runtime: {
|
||||
mode: 'mixed',
|
||||
public_origin_ready: true,
|
||||
cookie_secure: true,
|
||||
api_domain: 'https://hypertwist.app',
|
||||
website_domain: 'https://hypertwist.app',
|
||||
warnings: [],
|
||||
errors: [],
|
||||
},
|
||||
})
|
||||
mockGetReleaseManifest.mockResolvedValue({
|
||||
ok: true,
|
||||
manifest: {
|
||||
generated_at: '2026-06-22T12:00:00.000Z',
|
||||
support_email: 'hello@hypertwist.app',
|
||||
public_docs_url: 'https://docs.hypertwist.app',
|
||||
release_notes_url: 'https://notes.hypertwist.app',
|
||||
corresponding_source_url: 'https://hypertwist.app/open-source/source.zip',
|
||||
open_source_repo_url: 'https://github.com/hypertwist/hypertwist',
|
||||
viewer: {
|
||||
authenticated: false,
|
||||
canDownload: false,
|
||||
plan: null,
|
||||
role: null,
|
||||
accessStatus: null,
|
||||
},
|
||||
platforms: [
|
||||
{
|
||||
platform_key: 'windows',
|
||||
platform: 'Windows',
|
||||
subtitle: 'Primary shipping lane',
|
||||
details: 'Current packaged validation is strongest on the Windows Unreal lane.',
|
||||
configured: true,
|
||||
channel: 'candidate',
|
||||
version: '1.0.0',
|
||||
build_id: 'win64-1000',
|
||||
published_at: '2026-06-22T00:00:00.000Z',
|
||||
file_name: 'HyperTwist-Windows.zip',
|
||||
file_size_bytes: 1048576,
|
||||
checksum_sha256: 'abc123',
|
||||
download_url: null,
|
||||
download_available: false,
|
||||
validation_summary: {
|
||||
lane: 'Windows Unreal packaged validation',
|
||||
result: 'passed',
|
||||
generated_at: '2026-06-22T01:43:08.7625247Z',
|
||||
configuration: 'Development',
|
||||
skip_build: true,
|
||||
smoke_map_count: 2,
|
||||
smoke_maps: [
|
||||
{
|
||||
map_url: '/Game/HyperTwistTraining/Maps/L_HyperTwist_Magic120CellTraining',
|
||||
label: 'Magic120Cell dedicated-family training map',
|
||||
result: 'passed',
|
||||
},
|
||||
{
|
||||
map_url: '/Game/HyperTwistTraining/Maps/L_HyperTwist_MagicCube5DTraining',
|
||||
label: 'MagicCube5D dedicated-family training map',
|
||||
result: 'passed',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
})
|
||||
|
||||
renderWithProviders(<LaunchStatusPage />, ['/launch-status'])
|
||||
|
||||
expect(screen.getByText('Current launch-readiness checklist')).toBeTruthy()
|
||||
expect(screen.getByText('What must be true before public launch')).toBeTruthy()
|
||||
expect(screen.getByText('Launch hardening tracks')).toBeTruthy()
|
||||
expect(screen.getByText('Launch support and escalation lanes')).toBeTruthy()
|
||||
expect(screen.getByText('Choose the next launch move')).toBeTruthy()
|
||||
expect(screen.getByText('Release, notice, and support bundle')).toBeTruthy()
|
||||
expect(screen.getByText('Why launch authority stays in the browser shell')).toBeTruthy()
|
||||
expect(screen.getAllByText('Launch readiness').length).toBeGreaterThan(0)
|
||||
expect(
|
||||
screen.getAllByRole('link', { name: 'Open launch status' }).some((link) => link.getAttribute('href') === '/launch-status'),
|
||||
).toBe(true)
|
||||
expect(document.title).toBe('HyperTwist launch status | HyperTwist')
|
||||
expect(document.head.querySelector('meta[property="og:url"]')?.getAttribute('content')).toBe('https://hypertwist.app/launch-status')
|
||||
})
|
||||
|
||||
it('renders the release-notes page with the latest native selector-recall packet and rollout checklist', async () => {
|
||||
mockGetAuthHealth.mockResolvedValue({
|
||||
ok: true,
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ describe('public route registry', () => {
|
|||
expect(crawlablePublicRoutes.map((route) => route.path)).not.toContain('/login')
|
||||
expect(crawlablePublicRoutes.map((route) => route.path)).not.toContain('/register')
|
||||
expect(crawlablePublicRoutes.map((route) => route.path)).toContain('/getting-started')
|
||||
expect(crawlablePublicRoutes.map((route) => route.path)).toContain('/launch-status')
|
||||
})
|
||||
|
||||
it('carries non-empty loader metadata for every shared public-shell route', () => {
|
||||
|
|
@ -50,6 +51,7 @@ describe('public route registry', () => {
|
|||
expect(xml).toContain('<loc>https://hypertwist.app/</loc>')
|
||||
expect(xml).toContain('<loc>https://hypertwist.app/features</loc>')
|
||||
expect(xml).toContain('<loc>https://hypertwist.app/getting-started</loc>')
|
||||
expect(xml).toContain('<loc>https://hypertwist.app/launch-status</loc>')
|
||||
expect(xml).not.toContain('/login')
|
||||
expect(xml).not.toContain('/register')
|
||||
})
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ export function MarketingLaunchStatusBanner() {
|
|||
: `Live preview lane: remaining launch blockers are ${missingLabels.join(', ')}.`}
|
||||
</p>
|
||||
<div className="status-row">
|
||||
<Link className="inline-link" to="/pricing">
|
||||
<Link className="inline-link" to="/launch-status">
|
||||
View launch posture
|
||||
</Link>
|
||||
<Link className="inline-link" to={buildProtectedDownloadPath('windows')}>
|
||||
|
|
|
|||
|
|
@ -50,11 +50,12 @@ export const supportTopicGuidance: Record<string, SupportTopicGuide> = {
|
|||
'Keep notices and corresponding-source posture live before widening rollout.',
|
||||
],
|
||||
routeFocus: [
|
||||
'Pricing and download pages explain public launch posture and target selection.',
|
||||
'Launch-status, pricing, and download pages explain public launch posture and target selection.',
|
||||
'Public notices and terms pages carry the distribution and legal follow-through.',
|
||||
'The public manual explains the browser-versus-desktop product split that launch copy must preserve.',
|
||||
],
|
||||
actions: [
|
||||
{ label: 'Open launch status', to: '/launch-status' },
|
||||
{ label: 'Sign in for protected release lane', to: buildLoginPath(buildProtectedDownloadPath('windows')) },
|
||||
{ label: 'Sign in for protected notices', to: buildLoginPath('/app/notices') },
|
||||
{ label: 'Open pricing', to: '/pricing' },
|
||||
|
|
|
|||
|
|
@ -68,7 +68,8 @@ type StepCard = {
|
|||
|
||||
type StepOnlyCard = {
|
||||
title: string
|
||||
steps: readonly string[]
|
||||
steps?: readonly string[]
|
||||
bullets?: readonly string[]
|
||||
}
|
||||
|
||||
type FaqCard = {
|
||||
|
|
@ -173,7 +174,7 @@ function StepOnlyCardSection({
|
|||
<article key={card.title} className="card">
|
||||
<h3>{card.title}</h3>
|
||||
<ul className="list top-gap">
|
||||
{card.steps.map((step) => (
|
||||
{(card.steps ?? card.bullets ?? []).map((step) => (
|
||||
<li key={step}>{step}</li>
|
||||
))}
|
||||
</ul>
|
||||
|
|
@ -674,6 +675,11 @@ export function ResourcesPage() {
|
|||
<h3>Getting started</h3>
|
||||
<p>The canonical first-session path from browser access into the packaged desktop runtime.</p>
|
||||
</Link>
|
||||
<Link to="/launch-status" className="feature-band__card feature-band__card--link">
|
||||
<Landmark size={22} />
|
||||
<h3>Launch status</h3>
|
||||
<p>The canonical public checklist for preview-versus-launch posture, release authority, and rollout blockers.</p>
|
||||
</Link>
|
||||
<Link to="/docs" className="feature-band__card feature-band__card--link">
|
||||
<BookOpenText size={22} />
|
||||
<h3>Docs landing</h3>
|
||||
|
|
@ -855,6 +861,111 @@ export function ResourcesPage() {
|
|||
)
|
||||
}
|
||||
|
||||
function GettingStartedPageContent({
|
||||
releaseManifest,
|
||||
windowsValidationPlatform,
|
||||
}: Pick<ReturnType<typeof usePublicReleaseManifestView>, 'releaseManifest' | 'windowsValidationPlatform'>) {
|
||||
return (
|
||||
<>
|
||||
<OperatorDesktopQuickstartSection
|
||||
title="The first serious HyperTwist session"
|
||||
description="This quickstart stays faithful to the current product topology: browser first for identity and release posture, desktop first for the actual simulator."
|
||||
/>
|
||||
|
||||
<StepCardSection
|
||||
title="Operator path"
|
||||
description="These are the current first-party working stages from public discovery through protected release access and into the native simulator."
|
||||
cards={operatorManualTracks}
|
||||
/>
|
||||
|
||||
<Section
|
||||
title="Browser account access methods"
|
||||
description="The onboarding path is easier to trust when the shared-auth provider lineup is visible before operators cross into the protected shell."
|
||||
>
|
||||
<BrowserAuthMethodsGuide />
|
||||
</Section>
|
||||
|
||||
<Section
|
||||
title="First launch and desktop setup"
|
||||
description="These are the concrete checks that should happen immediately after the package is in hand."
|
||||
>
|
||||
<div className="card-grid">
|
||||
{desktopFirstLaunchCards.map((card) => (
|
||||
<article key={card.title} className="card">
|
||||
<h3>{card.title}</h3>
|
||||
<p>{card.description}</p>
|
||||
<ul className="list top-gap">
|
||||
{card.bullets.map((bullet) => (
|
||||
<li key={bullet}>{bullet}</li>
|
||||
))}
|
||||
</ul>
|
||||
</article>
|
||||
))}
|
||||
</div>
|
||||
</Section>
|
||||
|
||||
<BrowserDesktopRealitySection />
|
||||
|
||||
<Section
|
||||
title="Simulator use today"
|
||||
description="This keeps onboarding anchored to the lanes that actually execute in the current native runtime."
|
||||
>
|
||||
<div className="card-grid">
|
||||
{simulatorManualCards.map((card) => (
|
||||
<article key={card.title} className="card">
|
||||
<h3>{card.title}</h3>
|
||||
<p>{card.description}</p>
|
||||
<ul className="list top-gap">
|
||||
{card.bullets.map((bullet) => (
|
||||
<li key={bullet}>{bullet}</li>
|
||||
))}
|
||||
</ul>
|
||||
</article>
|
||||
))}
|
||||
</div>
|
||||
</Section>
|
||||
|
||||
<BulletCardSection
|
||||
title="Current control and device truth"
|
||||
description="This is the practical runtime boundary that first-session onboarding should teach directly instead of leaving as a later surprise."
|
||||
cards={inputAndDevicePostureCards}
|
||||
/>
|
||||
|
||||
<BulletCardSection
|
||||
title="Selectable control and settings roster"
|
||||
description="The current desktop runtime already has real profile and settings ownership, but it stays narrower than a finished XR/controller/preferences suite."
|
||||
cards={controlProfileRosterCards}
|
||||
/>
|
||||
|
||||
<SurfaceChoiceGuideSection description="Onboarding is smoother when the right next surface is explicit too: public for orientation, protected for entitled access, and desktop for simulator execution." />
|
||||
|
||||
<PublicReleaseDecisionGuideSection
|
||||
releaseManifest={releaseManifest}
|
||||
description="This onboarding lane should also tell operators whether the next honest move is protected desktop access, pricing/provisioning, browser/account continuity, or notices/source follow-through."
|
||||
/>
|
||||
|
||||
<PublicPackagedDesktopProofSection
|
||||
platform={windowsValidationPlatform}
|
||||
actions={[
|
||||
{ to: '/download', label: 'Open download center' },
|
||||
{ to: '/app', label: 'Open operator dashboard' },
|
||||
]}
|
||||
/>
|
||||
|
||||
<SupportTopicDirectorySection
|
||||
title="Need help on the way in?"
|
||||
description="Use these quick routes when the next onboarding step turns into a launch, access, or rollout issue."
|
||||
topics={supportTopicDirectory}
|
||||
/>
|
||||
|
||||
<ReleaseAuthorityBundleSection
|
||||
releaseManifest={releaseManifest}
|
||||
description="A professional onboarding page should keep docs, release notes, corresponding source, notices, and operator support visible as part of the same release story."
|
||||
/>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export function GettingStartedPage() {
|
||||
const { releaseManifest, windowsValidationPlatform } = usePublicReleaseManifestView('public-getting-started')
|
||||
|
||||
|
|
@ -870,100 +981,81 @@ export function GettingStartedPage() {
|
|||
title="Start in the browser. Train in the desktop runtime."
|
||||
lede="This page is the shortest complete operator path through the current product: resolve access, pair the installed runtime safely, verify the first session, and keep the real XR/controller boundary visible."
|
||||
>
|
||||
<OperatorDesktopQuickstartSection
|
||||
title="The first serious HyperTwist session"
|
||||
description="This quickstart stays faithful to the current product topology: browser first for identity and release posture, desktop first for the actual simulator."
|
||||
/>
|
||||
|
||||
<StepCardSection
|
||||
title="Operator path"
|
||||
description="These are the current first-party working stages from public discovery through protected release access and into the native simulator."
|
||||
cards={operatorManualTracks}
|
||||
/>
|
||||
|
||||
<Section
|
||||
title="Browser account access methods"
|
||||
description="The onboarding path is easier to trust when the shared-auth provider lineup is visible before operators cross into the protected shell."
|
||||
>
|
||||
<BrowserAuthMethodsGuide />
|
||||
</Section>
|
||||
|
||||
<Section
|
||||
title="First launch and desktop setup"
|
||||
description="These are the concrete checks that should happen immediately after the package is in hand."
|
||||
>
|
||||
<div className="card-grid">
|
||||
{desktopFirstLaunchCards.map((card) => (
|
||||
<article key={card.title} className="card">
|
||||
<h3>{card.title}</h3>
|
||||
<p>{card.description}</p>
|
||||
<ul className="list top-gap">
|
||||
{card.bullets.map((bullet) => (
|
||||
<li key={bullet}>{bullet}</li>
|
||||
))}
|
||||
</ul>
|
||||
</article>
|
||||
))}
|
||||
</div>
|
||||
</Section>
|
||||
|
||||
<BrowserDesktopRealitySection />
|
||||
|
||||
<Section
|
||||
title="Simulator use today"
|
||||
description="This keeps onboarding anchored to the lanes that actually execute in the current native runtime."
|
||||
>
|
||||
<div className="card-grid">
|
||||
{simulatorManualCards.map((card) => (
|
||||
<article key={card.title} className="card">
|
||||
<h3>{card.title}</h3>
|
||||
<p>{card.description}</p>
|
||||
<ul className="list top-gap">
|
||||
{card.bullets.map((bullet) => (
|
||||
<li key={bullet}>{bullet}</li>
|
||||
))}
|
||||
</ul>
|
||||
</article>
|
||||
))}
|
||||
</div>
|
||||
</Section>
|
||||
|
||||
<BulletCardSection
|
||||
title="Current control and device truth"
|
||||
description="This is the practical runtime boundary that first-session onboarding should teach directly instead of leaving as a later surprise."
|
||||
cards={inputAndDevicePostureCards}
|
||||
/>
|
||||
|
||||
<BulletCardSection
|
||||
title="Selectable control and settings roster"
|
||||
description="The current desktop runtime already has real profile and settings ownership, but it stays narrower than a finished XR/controller/preferences suite."
|
||||
cards={controlProfileRosterCards}
|
||||
/>
|
||||
|
||||
<SurfaceChoiceGuideSection description="Onboarding is smoother when the right next surface is explicit too: public for orientation, protected for entitled access, and desktop for simulator execution." />
|
||||
|
||||
<PublicReleaseDecisionGuideSection
|
||||
<GettingStartedPageContent
|
||||
releaseManifest={releaseManifest}
|
||||
description="This onboarding lane should also tell operators whether the next honest move is protected desktop access, pricing/provisioning, browser/account continuity, or notices/source follow-through."
|
||||
windowsValidationPlatform={windowsValidationPlatform}
|
||||
/>
|
||||
</MarketingShell>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export function LaunchStatusPage() {
|
||||
const { releaseManifest, windowsValidationPlatform } = usePublicReleaseManifestView('public-launch-status')
|
||||
|
||||
return (
|
||||
<>
|
||||
<SiteMetadata
|
||||
title="HyperTwist launch status"
|
||||
description="Check the canonical HyperTwist public launch-readiness posture: checkout, download, notices, corresponding source, public auth runtime, and release authority."
|
||||
canonicalPath="/launch-status"
|
||||
/>
|
||||
<MarketingShell
|
||||
eyebrow="Launch authority"
|
||||
title="See exactly what still separates preview from public launch."
|
||||
lede="This is the canonical public authority surface for rollout truth: release targets, checkout posture, notices, corresponding source, and public auth-runtime readiness stay visible here in one place instead of being reconstructed from scattered callouts."
|
||||
>
|
||||
<Section
|
||||
title="Current public launch status"
|
||||
description="Use this page when rollout language, pricing, download, and legal/distribution follow-through need one authoritative browser-owned checklist."
|
||||
>
|
||||
<PublicLaunchStatus title="Current launch-readiness checklist" />
|
||||
</Section>
|
||||
|
||||
<StepOnlyCardSection
|
||||
title="What must be true before public launch"
|
||||
description="These are the bounded rollout checks that keep external launch language tied to real release authority instead of aspiration."
|
||||
cards={releaseRolloutChecklist}
|
||||
/>
|
||||
|
||||
<StepOnlyCardSection
|
||||
title="Launch hardening tracks"
|
||||
description="These are the practical work tracks for turning a truthful preview lane into a production-grade public release lane."
|
||||
cards={deploymentReadinessTracks}
|
||||
/>
|
||||
|
||||
<PublicPackagedDesktopProofSection
|
||||
platform={windowsValidationPlatform}
|
||||
actions={[
|
||||
{ to: '/download', label: 'Open download center' },
|
||||
{ to: '/app', label: 'Open operator dashboard' },
|
||||
{ to: '/getting-started', label: 'Open getting started' },
|
||||
]}
|
||||
/>
|
||||
|
||||
<SupportTopicDirectorySection
|
||||
title="Need help on the way in?"
|
||||
description="Use these quick routes when the next onboarding step turns into a launch, access, or rollout issue."
|
||||
title="Launch support and escalation lanes"
|
||||
description="Launch posture only helps when the next human lane is explicit too, so these support routes stay attached to the same authority surface."
|
||||
topics={supportTopicDirectory}
|
||||
selectedTopicKey="launch-readiness"
|
||||
/>
|
||||
|
||||
<PublicReleaseDecisionGuideSection
|
||||
releaseManifest={releaseManifest}
|
||||
title="Choose the next launch move"
|
||||
description="This page should not stop at checklist language. It should also say whether the next honest move is protected desktop access, pricing/provisioning, browser/account follow-through, or notices/source review."
|
||||
/>
|
||||
|
||||
<ReleaseAuthorityBundleSection
|
||||
releaseManifest={releaseManifest}
|
||||
description="A professional onboarding page should keep docs, release notes, corresponding source, notices, and operator support visible as part of the same release story."
|
||||
title="Release, notice, and support bundle"
|
||||
description="Launch readiness is only trustworthy when docs, release notes, corresponding source, public notices, and operator contact remain visible as one release bundle."
|
||||
/>
|
||||
|
||||
<SurfaceChoiceGuideSection description="This keeps launch posture grounded in the real product topology too: public for launch truth, protected for account-aware release work, and native for the simulator itself." />
|
||||
|
||||
<BrowserDesktopRealitySection
|
||||
title="Why launch authority stays in the browser shell"
|
||||
description="Launch-readiness posture belongs to the distribution shell because checkout, notices, release references, and account access are browser-owned even while the actual training runtime remains native."
|
||||
/>
|
||||
</MarketingShell>
|
||||
</>
|
||||
|
|
|
|||
|
|
@ -49,6 +49,16 @@
|
|||
"footer": true,
|
||||
"crawlable": true
|
||||
},
|
||||
{
|
||||
"path": "/launch-status",
|
||||
"label": "Launch Status",
|
||||
"loaderTitle": "Launch status",
|
||||
"loaderEyebrow": "Launch authority",
|
||||
"loaderDescription": "Loading the canonical public launch-readiness checklist, release posture, and preview-versus-launch authority map.",
|
||||
"nav": false,
|
||||
"footer": true,
|
||||
"crawlable": true
|
||||
},
|
||||
{
|
||||
"path": "/docs",
|
||||
"label": "Docs",
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ const FeaturesPage = lazy(() => import('../pages/public-pages-features').then((m
|
|||
const AboutPage = lazy(() => import('../pages/public-pages-marketing').then((m) => ({ default: m.AboutPage })))
|
||||
const ResourcesPage = lazy(() => import('../pages/public-pages-marketing').then((m) => ({ default: m.ResourcesPage })))
|
||||
const GettingStartedPage = lazy(() => import('../pages/public-pages-marketing').then((m) => ({ default: m.GettingStartedPage })))
|
||||
const LaunchStatusPage = lazy(() => import('../pages/public-pages-marketing').then((m) => ({ default: m.LaunchStatusPage })))
|
||||
const DocsPage = lazy(() => import('../pages/public-pages-marketing').then((m) => ({ default: m.DocsPage })))
|
||||
const SupportPage = lazy(() => import('../pages/public-pages-marketing').then((m) => ({ default: m.SupportPage })))
|
||||
const ChangelogPage = lazy(() => import('../pages/public-pages-marketing').then((m) => ({ default: m.ChangelogPage })))
|
||||
|
|
@ -26,6 +27,7 @@ const publicRouteElements: Record<string, ReactNode> = {
|
|||
'/about': <AboutPage />,
|
||||
'/resources': <ResourcesPage />,
|
||||
'/getting-started': <GettingStartedPage />,
|
||||
'/launch-status': <LaunchStatusPage />,
|
||||
'/docs': <DocsPage />,
|
||||
'/support': <SupportPage />,
|
||||
'/changelog': <ChangelogPage />,
|
||||
|
|
|
|||
|
|
@ -819,6 +819,7 @@ export const resourceCollections = [
|
|||
items: [
|
||||
'Feature registry-backed descriptions only',
|
||||
'Dedicated getting-started route for the first real browser-to-desktop operator journey',
|
||||
'Dedicated launch-status route for the canonical preview-versus-launch authority surface',
|
||||
'Public feature atlas for the real browser-versus-desktop product split',
|
||||
'Roadmap-honest separation between shipped and retained capability',
|
||||
'Release notes that surface what actually landed',
|
||||
|
|
@ -864,6 +865,11 @@ export const resourceCollections = [
|
|||
] as const
|
||||
|
||||
export const changelogEntries = [
|
||||
{
|
||||
date: 'June 27, 2026',
|
||||
title: 'Launch status now has its own canonical public authority route',
|
||||
details: 'HyperTwist now exposes a dedicated public `/launch-status` surface for the live launch-readiness checklist, rollout tracks, packaged desktop proof, release references, and the exact preview-versus-launch blockers, so launch truth no longer has to be reconstructed from pricing plus scattered callouts.',
|
||||
},
|
||||
{
|
||||
date: 'June 27, 2026',
|
||||
title: 'A dedicated getting-started route now anchors the public onboarding story',
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue