chore: flip docs pages to canonical URLs (#822)

* chore: flip docs pages to canonical URLs

* * update hero CTA to have public mesh link at smaller breakpoints

* * small DOCS_URL fixup

* One more

* Fix failing ui-quality: canonicalize remaining docs links to meshllm.cloud

ConfigurationPage source had reverted OWNER_CONTROL_DOCS_URL to
docs.meshllm.cloud/ while its test still expected meshllm.cloud/, so
ui-quality was failing. Align the source with the test and fix the two
remaining DOCS_URL constants (AppHeader, ChatPage) that were still on
docs.meshllm.cloud and used with marketing-home anchors (#agents/#install/
#blackboard) that only exist on the apex.

---------

Co-authored-by: Michael Neale <michael.neale@gmail.com>
This commit is contained in:
Nick DiZazzo 2026-06-10 21:54:54 -04:00 committed by GitHub
parent f9691eaf70
commit 86ef4ded7f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
17 changed files with 87 additions and 58 deletions

View file

@ -332,7 +332,7 @@ ui-dev api="http://127.0.0.1:3131" port="5173":
MESH_UI_API_ORIGIN="{{ api }}" VITE_API_URL="{{ api }}" pnpm run dev -- --host 0.0.0.0 --port {{ port }}
# Run the UI dev server proxying to the public meshllm.cloud API
ui-dev-public: (ui-dev "https://meshllm.cloud")
ui-dev-public: (ui-dev "https://public.meshllm.cloud")
# Build the public website into docs/ for static hosting.
website-build:
@ -422,7 +422,7 @@ test-all:
echo "No server on port 3131 — starting UI dev server with public mesh..."
# Start dev server in background, capture PID tree for cleanup
MESH_UI_API_ORIGIN="https://meshllm.cloud" VITE_API_URL="https://meshllm.cloud" bash -c 'cd "{{ ui_dir }}" && pnpm exec vite --host 0.0.0.0 --port 5173' &
MESH_UI_API_ORIGIN="https://public.meshllm.cloud" VITE_API_URL="https://public.meshllm.cloud" bash -c 'cd "{{ ui_dir }}" && pnpm exec vite --host 0.0.0.0 --port 5173' &
DEV_PID=$!
# Wait for dev server to be ready (up to 30s)

View file

@ -38,7 +38,7 @@ In plain terms: MeshLLM exists because powerful open models should not require e
## Who made it
The public origin statement on docs.meshllm.cloud is signed by **Mic N**. Public GitHub contributor data for `Mesh-LLM/mesh-llm` identifies these top three human contributors:
The public origin statement on meshllm.cloud is signed by **Mic N**. Public GitHub contributor data for `Mesh-LLM/mesh-llm` identifies these top three human contributors:
1. **Michael Neale** (`michaelneale`)
2. **James Dumay** (`i386`)

View file

@ -19,7 +19,7 @@ import { cn } from '@/lib/utils'
import { env } from '@/lib/env'
import type { TopSection } from '@/features/app-shell/lib/routes'
const DOCS_URL = 'https://docs.meshllm.cloud'
const DOCS_URL = 'https://meshllm.cloud'
type ThemeMode = 'auto' | 'light' | 'dark'

View file

@ -2060,7 +2060,7 @@ export const DASHBOARD_HARNESS: DashboardHarnessData = {
description:
'Build personal AI from open models. Pool machines across your home, office, or friends — no cloud needed.',
actions: [
{ label: 'Learn more', href: 'https://docs.meshllm.cloud/', tone: 'link' },
{ label: 'Learn more', href: 'https://meshllm.cloud/', tone: 'link' },
{ label: 'GitHub', href: 'https://github.com/Mesh-LLM/mesh-llm', tone: 'secondary' }
]
},
@ -2071,7 +2071,7 @@ export const DASHBOARD_HARNESS: DashboardHarnessData = {
meshNodeSeeds: MESH_NODES,
meshId: 'dashboard-mesh',
connect: {
installHref: 'https://docs.meshllm.cloud/#install',
installHref: 'https://meshllm.cloud/#install',
apiStatus: 'configured target',
runCommand: 'mesh-llm --auto --join <mesh-invite-token>',
description: 'contribute compute to the mesh'
@ -2097,11 +2097,11 @@ export const DASHBOARD_HARNESS: DashboardHarnessData = {
export const SHELL_HARNESS: ShellHarnessData = {
productName: 'mesh-llm',
brand: { primary: 'mesh', accent: 'llm' },
footerLinks: [{ label: 'Docs', href: 'https://docs.meshllm.cloud/' }],
footerLinks: [{ label: 'Docs', href: 'https://meshllm.cloud/' }],
footerTrailingLink: { label: 'GitHub', href: 'https://github.com/Mesh-LLM/mesh-llm' },
topNavApiAccessLinks: [
{ href: 'https://docs.meshllm.cloud/', label: 'Docs' },
{ href: 'https://docs.meshllm.cloud/#install', label: 'Install' }
{ href: 'https://meshllm.cloud/', label: 'Docs' },
{ href: 'https://meshllm.cloud/#install', label: 'Install' }
],
topNavJoinCommands: [
{
@ -2119,9 +2119,9 @@ export const SHELL_HARNESS: ShellHarnessData = {
{ label: 'Client-only join command', value: 'mesh-llm client --join <mesh-invite-token>', prefix: '$' }
],
topNavJoinLinks: [
{ href: 'https://docs.meshllm.cloud/', label: 'Setup' },
{ href: 'https://docs.meshllm.cloud/#install', label: 'Install' },
{ href: 'https://docs.meshllm.cloud/#blackboard', label: 'Blackboard' }
{ href: 'https://meshllm.cloud/', label: 'Setup' },
{ href: 'https://meshllm.cloud/#install', label: 'Install' },
{ href: 'https://meshllm.cloud/#blackboard', label: 'Blackboard' }
]
}

View file

@ -34,7 +34,7 @@ import { ChatComposer } from '@/features/chat/components/composer/ChatComposer'
import { ChatBubble } from '@/features/chat/components/messages/ChatBubble'
import { ConversationList } from '@/features/chat/components/sidebar/ConversationList'
const DOCS_URL = 'https://docs.meshllm.cloud'
const DOCS_URL = 'https://meshllm.cloud'
function visionBadge(model?: MeshModel | null) {
if (!model) return null

View file

@ -357,7 +357,7 @@ describe('ConfigurationPage', () => {
screen.getByText('No owner-control identity on this node, run both commands to unlock saving.')
).toBeInTheDocument()
expect(screen.getByText('missing owner identity')).toBeInTheDocument()
expect(screen.getByRole('link', { name: /docs/i })).toHaveAttribute('href', 'https://docs.meshllm.cloud/')
expect(screen.getByRole('link', { name: /docs/i })).toHaveAttribute('href', 'https://meshllm.cloud/')
expect(screen.queryByRole('button', { name: /copy both/i })).not.toBeInTheDocument()
expect(screen.getAllByText('mesh-llm')).toHaveLength(2)
expect(screen.getByText('auth')).toBeInTheDocument()

View file

@ -71,7 +71,7 @@ type ConfigurationPageProps = {
const OWNER_CONTROL_READ_ONLY_MESSAGE = 'No owner-control identity on this node, run both commands to unlock saving.'
const OWNER_CONTROL_SAVE_ERROR = 'Config was not saved. Runtime control is disabled: missing owner identity.'
const RUNTIME_CONTROL_SAVE_UNAVAILABLE_ERROR = 'Config was not saved. Runtime control config is unavailable.'
const OWNER_CONTROL_DOCS_URL = 'https://docs.meshllm.cloud/'
const OWNER_CONTROL_DOCS_URL = 'https://meshllm.cloud/'
function formatRuntimeControlDisabledReason(bootstrap: RuntimeControlBootstrapPayload | undefined) {
if (bootstrap?.disabled_reason === 'missing_owner_identity') return 'missing owner identity'

View file

@ -5,7 +5,7 @@ import { ConnectBlock, type ConnectApiTargetLiveness } from '@/features/network/
function renderConnectBlock(apiTargetLiveness?: ConnectApiTargetLiveness) {
render(
<ConnectBlock
installHref="https://docs.meshllm.cloud/#install"
installHref="https://meshllm.cloud/#install"
apiUrl="http://127.0.0.1:9337/v1"
apiStatus="configured target"
apiTargetLiveness={apiTargetLiveness}

View file

@ -188,8 +188,8 @@ describe('TopNav', () => {
renderTopNav({
apiUrl: 'http://mesh.local:3131/v1',
apiAccessLinks: [
{ href: 'https://docs.meshllm.cloud/', label: 'Docs' },
{ href: 'https://docs.meshllm.cloud/#install', label: 'Install' }
{ href: 'https://meshllm.cloud/', label: 'Docs' },
{ href: 'https://meshllm.cloud/#install', label: 'Install' }
],
joinCommands: [
{
@ -210,9 +210,9 @@ describe('TopNav', () => {
}
],
joinLinks: [
{ href: 'https://docs.meshllm.cloud/', label: 'Setup' },
{ href: 'https://docs.meshllm.cloud/#install', label: 'Install' },
{ href: 'https://docs.meshllm.cloud/#blackboard', label: 'Blackboard' }
{ href: 'https://meshllm.cloud/', label: 'Setup' },
{ href: 'https://meshllm.cloud/#install', label: 'Install' },
{ href: 'https://meshllm.cloud/#blackboard', label: 'Blackboard' }
]
})

View file

@ -260,8 +260,8 @@ function HeaderLinks({ links }: { links: { href: string; label: string }[] }) {
}
const DEFAULT_API_ACCESS_LINKS: LinkItem[] = [
{ href: 'https://docs.meshllm.cloud/', label: 'Docs' },
{ href: 'https://docs.meshllm.cloud/#install', label: 'Install' }
{ href: 'https://meshllm.cloud/', label: 'Docs' },
{ href: 'https://meshllm.cloud/#install', label: 'Install' }
]
function ApiAccessContent({ apiUrl, dataMode, links }: { apiUrl: string; dataMode: DataMode; links?: LinkItem[] }) {
@ -329,9 +329,9 @@ const DEFAULT_JOIN_COMMANDS: TopNavJoinCommand[] = [
]
const DEFAULT_JOIN_LINKS: LinkItem[] = [
{ href: 'https://docs.meshllm.cloud/', label: 'Setup' },
{ href: 'https://docs.meshllm.cloud/#install', label: 'Install' },
{ href: 'https://docs.meshllm.cloud/#blackboard', label: 'Blackboard' }
{ href: 'https://meshllm.cloud/', label: 'Setup' },
{ href: 'https://meshllm.cloud/#install', label: 'Install' },
{ href: 'https://meshllm.cloud/#blackboard', label: 'Blackboard' }
]
function JoinInviteContent({ commands, links }: { commands?: TopNavJoinCommand[]; links?: LinkItem[] }) {

View file

@ -6,19 +6,19 @@
<span class="green"></span>
</div>
<div class="cta-terminal-tabs" role="tablist" aria-label="Install methods">
<button class="active" type="button" role="tab" aria-selected="true" data-install-method="curl" data-install-copy="curl -fsSL https://mesh-llm.cloud/install.sh | sh">curl</button>
<button class="active" type="button" role="tab" aria-selected="true" data-install-method="curl" data-install-copy="curl -fsSL https://meshllm.cloud/install.sh | sh">curl</button>
<button type="button" role="tab" aria-selected="false" data-install-method="brew" data-install-copy="brew install mesh-llm/tap/mesh-llm">brew</button>
<button type="button" role="tab" aria-selected="false" data-install-method="cargo" data-install-copy="cargo install mesh-llm">cargo</button>
</div>
<div class="cta-terminal-meta">~ &middot; zsh &middot; mesh-llm</div>
<button class="cta-copy" type="button" data-copy-text="curl -fsSL https://mesh-llm.cloud/install.sh | sh" aria-label="Copy install command">COPY</button>
<button class="cta-copy" type="button" data-copy-text="curl -fsSL https://meshllm.cloud/install.sh | sh" aria-label="Copy install command">COPY</button>
</div>
<div class="cta-terminal-body">
<div class="cta-terminal-block">
<p class="comment"># Install Mesh (macOS, Linux, Windows &middot; ~18 MB)</p>
<p class="cta-install-command" data-install-command-display aria-live="polite"><span class="prompt">$</span> <span class="cmd">curl</span> <span class="flag">-fsSL</span> <span class="value">https://mesh-llm.cloud/install.sh</span> <span class="pipe">|</span> <span class="cmd">sh</span></p>
<template data-install-template="curl"><span class="prompt">$</span> <span class="cmd">curl</span> <span class="flag">-fsSL</span> <span class="value">https://mesh-llm.cloud/install.sh</span> <span class="pipe">|</span> <span class="cmd">sh</span></template>
<p class="cta-install-command" data-install-command-display aria-live="polite"><span class="prompt">$</span> <span class="cmd">curl</span> <span class="flag">-fsSL</span> <span class="value">https://meshllm.cloud/install.sh</span> <span class="pipe">|</span> <span class="cmd">sh</span></p>
<template data-install-template="curl"><span class="prompt">$</span> <span class="cmd">curl</span> <span class="flag">-fsSL</span> <span class="value">https://meshllm.cloud/install.sh</span> <span class="pipe">|</span> <span class="cmd">sh</span></template>
<template data-install-template="brew"><span class="prompt">$</span> <span class="cmd">brew</span> <span class="cmd">install</span> <span class="value">mesh-llm/tap/mesh-llm</span></template>
<template data-install-template="cargo"><span class="prompt">$</span> <span class="cmd">cargo</span> <span class="cmd">install</span> <span class="value">mesh-llm</span></template>
</div>

View file

@ -16,15 +16,19 @@
<code class="min-w-0 overflow-hidden text-ellipsis whitespace-nowrap text-xs sm:text-sm">
<span class="cmd">curl</span>
<span class="flag">-fsSL</span>
<span class="value">https://mesh-llm.cloud/install.sh</span>
<span class="value">https://meshllm.cloud/install.sh</span>
<span class="pipe">|</span>
<span class="cmd">sh</span>
</code>
<button class="hero-copy inline-flex shrink-0 items-center justify-center p-0 text-muted hover:text-fg" type="button" data-copy-text="curl -fsSL https://mesh-llm.cloud/install.sh | sh" aria-label="Copy install command" title="Copy install command">
<button class="hero-copy inline-flex shrink-0 items-center justify-center p-0 text-muted hover:text-fg" type="button" data-copy-text="curl -fsSL https://meshllm.cloud/install.sh | sh" aria-label="Copy install command" title="Copy install command">
<i data-lucide="copy" aria-hidden="true"></i>
</button>
</div>
<a class="hero-learn inline-flex min-h-12 items-center justify-center gap-2 rounded-mesh border border-line-soft px-4 text-sm font-semibold text-muted hover:text-fg" href="#topology">
<a class="hero-public inline-flex min-h-12 items-center justify-center gap-2 rounded-mesh px-4 text-sm font-semibold" href="{{ site.publicMeshUrl }}">
<span>Public mesh</span>
<i data-lucide="share-2" aria-hidden="true"></i>
</a>
<a class="hero-learn inline-flex min-h-12 items-center justify-center gap-2 rounded-mesh px-4 text-sm font-semibold" href="#topology">
<span>Learn more</span>
<i data-lucide="arrow-down" aria-hidden="true"></i>
</a>

View file

@ -1426,25 +1426,40 @@ section.hero::after {
}
.hero-copy.copied { color: var(--green-2); }
.hero-copy.failed { color: #fca5a5; }
.hero-learn {
.hero-learn,
.hero-public {
min-height: 48px;
display: inline-flex;
align-items: center;
gap: 10px;
padding: 0 16px;
border: 1px solid var(--line-3);
border-radius: var(--radius);
color: var(--fg-2);
font-weight: 500;
transition: border-color 0.16s ease, color 0.16s ease, background-color 0.16s ease;
}
.hero-learn {
border: 1px solid var(--line-3);
background: transparent;
color: var(--fg-2);
}
.hero-learn:hover {
border-color: rgba(59,130,246,0.48);
background: var(--blue-soft);
color: var(--fg);
}
.hero-public {
border: 1px solid var(--primary);
background: var(--primary);
color: var(--primary-foreground);
}
.hero-public:hover {
border-color: var(--primary-hover);
background: var(--primary-hover);
color: var(--primary-foreground);
}
.hero-copy:focus-visible,
.hero-learn:focus-visible,
.hero-public:focus-visible,
.sponsor-slot:focus-visible {
outline: 2px solid var(--blue);
outline-offset: 2px;
@ -1452,7 +1467,9 @@ section.hero::after {
.hero-copy svg,
.hero-copy i,
.hero-learn svg,
.hero-learn i {
.hero-learn i,
.hero-public svg,
.hero-public i {
width: 16px;
height: 16px;
stroke-width: 1.8;
@ -1462,6 +1479,10 @@ section.hero::after {
color: var(--subtle);
will-change: transform, opacity;
}
.hero-public svg,
.hero-public i {
color: currentColor;
}
.hero-sponsor {
flex: 0 0 auto;
display: flex;
@ -1582,21 +1603,25 @@ section.hero::after {
}
.hero-footer-actions {
display: grid;
grid-template-columns: 1fr;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 10px;
width: 100%;
}
.hero-sponsor {
display: none;
}
.hero-install,
.hero-learn {
.hero-learn,
.hero-public {
width: 100%;
max-width: none;
}
.hero-install {
grid-column: 1 / -1;
justify-content: space-between;
}
.hero-learn {
.hero-learn,
.hero-public {
justify-content: center;
}
.hero-title-loop {

View file

@ -9,7 +9,7 @@ Install Mesh on every Linux machine that should serve a model or call into a mes
## Quick install
```sh
curl -fsSL https://mesh-llm.cloud/install.sh | bash
curl -fsSL https://meshllm.cloud/install.sh | bash
```
Open a new terminal after install if the installer added Mesh to your `PATH`.
@ -34,7 +34,7 @@ The installer auto-detects your GPU and selects the best bundle. Supported Linux
Force a specific flavor:
```sh
curl -fsSL https://mesh-llm.cloud/install.sh | bash -s -- --flavor cuda
curl -fsSL https://meshllm.cloud/install.sh | bash -s -- --flavor cuda
```
## What the installer does
@ -46,13 +46,13 @@ The installer detects your Linux hardware, selects the matching release bundle,
Install the latest prerelease:
```sh
curl -fsSL https://mesh-llm.cloud/install.sh | bash -s -- --pre-release
curl -fsSL https://meshllm.cloud/install.sh | bash -s -- --pre-release
```
Install to a custom location:
```sh
curl -fsSL https://mesh-llm.cloud/install.sh | bash -s -- --install-dir "$HOME/bin"
curl -fsSL https://meshllm.cloud/install.sh | bash -s -- --install-dir "$HOME/bin"
```
## Next step

View file

@ -9,7 +9,7 @@ Install Mesh on every Mac that should serve a model or call into a mesh.
## Quick install
```sh
curl -fsSL https://mesh-llm.cloud/install.sh | bash
curl -fsSL https://meshllm.cloud/install.sh | bash
```
Open a new terminal after install if the installer added Mesh to your `PATH`.
@ -37,7 +37,7 @@ The installer detects your Mac hardware, selects the `metal` bundle (optimized f
The macOS installer auto-detects `metal`. Force a different flavor when auto-detection is wrong or you want to test a specific backend:
```sh
curl -fsSL https://mesh-llm.cloud/install.sh | bash -s -- --flavor vulkan
curl -fsSL https://meshllm.cloud/install.sh | bash -s -- --flavor vulkan
```
Available macOS flavors:
@ -53,13 +53,13 @@ Available macOS flavors:
Install the latest prerelease:
```sh
curl -fsSL https://mesh-llm.cloud/install.sh | bash -s -- --pre-release
curl -fsSL https://meshllm.cloud/install.sh | bash -s -- --pre-release
```
Install to a custom location:
```sh
curl -fsSL https://mesh-llm.cloud/install.sh | bash -s -- --install-dir "$HOME/bin"
curl -fsSL https://meshllm.cloud/install.sh | bash -s -- --install-dir "$HOME/bin"
```
## Next step

View file

@ -11,7 +11,7 @@ Install Mesh on every Windows machine that should serve a model or call into a m
Open PowerShell and run:
```powershell
irm https://mesh-llm.cloud/install.ps1 | iex
irm https://meshllm.cloud/install.ps1 | iex
```
Open a new terminal after install if the installer added Mesh to your `PATH`.
@ -36,7 +36,7 @@ The installer auto-detects your GPU and selects the best bundle. Supported Windo
Force a specific flavor:
```powershell
& ([scriptblock]::Create((irm https://mesh-llm.cloud/install.ps1))) -Flavor cuda
& ([scriptblock]::Create((irm https://meshllm.cloud/install.ps1))) -Flavor cuda
```
## What the installer does
@ -48,13 +48,13 @@ The installer detects your Windows hardware, selects the matching release bundle
Install the latest prerelease:
```powershell
& ([scriptblock]::Create((irm https://mesh-llm.cloud/install.ps1))) -PreRelease
& ([scriptblock]::Create((irm https://meshllm.cloud/install.ps1))) -PreRelease
```
Install to a custom location:
```powershell
& ([scriptblock]::Create((irm https://mesh-llm.cloud/install.ps1))) -InstallDir "$HOME\bin"
& ([scriptblock]::Create((irm https://meshllm.cloud/install.ps1))) -InstallDir "$HOME\bin"
```
## Next step

View file

@ -12,24 +12,24 @@ Choose your platform for the fastest path:
{% set macosQuick %}
```sh
curl -fsSL https://mesh-llm.cloud/install.sh | bash
curl -fsSL https://meshllm.cloud/install.sh | bash
```
{% endset %}
{% set linuxQuick %}
```sh
curl -fsSL https://mesh-llm.cloud/install.sh | bash
curl -fsSL https://meshllm.cloud/install.sh | bash
```
{% endset %}
{% set windowsQuick %}
```powershell
irm https://mesh-llm.cloud/install.ps1 | iex
irm https://meshllm.cloud/install.ps1 | iex
```
{% endset %}
**macOS** &mdash; Metal (Apple Silicon):
```sh
curl -fsSL https://mesh-llm.cloud/install.sh | bash
curl -fsSL https://meshllm.cloud/install.sh | bash
```
Full guide: [Installing on macOS](/docs/pages/installing-macos/)
@ -37,7 +37,7 @@ Full guide: [Installing on macOS](/docs/pages/installing-macos/)
**Linux** &mdash; CUDA, ROCm, Vulkan, or CPU:
```sh
curl -fsSL https://mesh-llm.cloud/install.sh | bash
curl -fsSL https://meshllm.cloud/install.sh | bash
```
Full guide: [Installing on Linux](/docs/pages/installing-linux/)
@ -45,7 +45,7 @@ Full guide: [Installing on Linux](/docs/pages/installing-linux/)
**Windows** &mdash; CUDA, ROCm, Vulkan, or CPU:
```powershell
irm https://mesh-llm.cloud/install.ps1 | iex
irm https://meshllm.cloud/install.ps1 | iex
```
Full guide: [Installing on Windows](/docs/pages/installing-windows/)