Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ <h1>Share a live terminal in any browser.</h1>
<p>Run <code>shell login</code> to link a machine to an account. Sessions from every linked machine then appear together in a web app, open as tabs you can type into, and can be created or killed from the browser. Agree once and a machine can also be given work from there: pick a machine, pick what to run, and it starts on that machine with a password the browser seals so the service cannot read it.</p>
<p>Signing up creates an organization. Invite links add people, everyone inside sees every member’s sessions, and each session has an owner who can hand it off. Comments, mentions, and notifications add context without copying terminal input into the accounts service.</p>
<p>shell.online is developed by <a href="https://pilotprotocol.network/">Pilot Protocol</a>.</p>
<p><a href="https://app.shell.online/signup">Sign up free at app.shell.online</a>, or install the command-line tool:</p>
<p><code>curl -fsSL https://shell.online/install | sh</code></p>
<p><a href="https://github.com/TeoSlayer/shell.online">Read the source and installation guide on GitHub</a>.</p>
</div>
Expand Down
9 changes: 9 additions & 0 deletions scripts/test-landing-seo.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,15 @@ check(indexHtml.includes("<noscript>"), "Crawlable no-script product summary is
check((landingMarkup.match(/<h1[ >]/gu) ?? []).length === 1, "Landing page must have exactly one primary heading");
check(landingMarkup.includes('id="use-cases"'), "Visible use-case section is missing");

/*
* app.shell.online is the other front door, and it is easy to lose in a
* refactor because the install one-liner reads like the only call to action.
* Pin both buttons and the no-script link so the account cannot go quiet.
*/
check(landingMarkup.includes('class="hero-signup" href="${SIGNUP_URL}"'), "Hero account button is missing");
check(landingMarkup.includes('class="nav-signup" href="${SIGNUP_URL}"'), "Header account button is missing");
check(indexHtml.includes("https://app.shell.online/signup"), "No-script account link is missing");
Comment thread
Alexgodoroja marked this conversation as resolved.
Dismissed

for (const metadata of [
'<meta property="og:type" content="website"',
'<meta property="og:site_name" content="shell.online"',
Expand Down
109 changes: 79 additions & 30 deletions web/landing.css
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,32 @@
transform: translateY(-1px);
}

/*
* The account button rides in the header on every scroll position, so it is
* the accent control rather than another dark pill: two identically filled
* pills side by side would read as one widget split in half.
*/
.nav-signup {
display: inline-flex;
height: 44px;
padding: 0 19px;
border: 1px solid #b3e336;
border-radius: 999px;
background: var(--acid);
color: #171a13 !important;
font-size: 12px;
font-weight: 620;
text-decoration: none;
align-items: center;
white-space: nowrap;
transition: transform 150ms ease, background 150ms ease;
}

.nav-signup:hover {
background: #d6ff7a;
transform: translateY(-1px);
}

.marketing-hero {
display: grid;
width: min(1240px, calc(100% - 64px));
Expand Down Expand Up @@ -513,37 +539,46 @@
}

/*
* The account route in, beside the install command rather than instead of it.
* Underlined rather than boxed: two filled controls next to each other would
* argue about which is the thing to press, and the install one-liner is still
* the faster start.
* app.shell.online is live, so the account is a destination and not a footnote
* to the install line. It leads the hero as the one accent-filled control on
* the page. The install one-liner keeps its dark terminal styling directly
* below: same size, so the pair reads as a ranked choice rather than two
* controls arguing about which is the thing to press.
*/
.hero-signup,
.platform-signup {
color: #22241f;
font-size: 13px;
font-weight: 560;
text-decoration: underline;
text-decoration-color: #b9b6ab;
text-underline-offset: 4px;
white-space: nowrap;
transition: text-decoration-color 150ms ease;
.hero-signup {
display: grid;
height: 58px;
padding: 0 22px;
border: 1px solid #b3e336;
border-radius: 10px;
background: var(--acid);
box-shadow: 0 12px 30px rgb(147 194 40 / 30%);
color: #171a13;
font-size: 16px;
letter-spacing: -0.015em;
text-decoration: none;
grid-template-columns: minmax(0, 1fr) auto;
align-items: center;
gap: 12px;
transition: transform 160ms ease, box-shadow 160ms ease, background 160ms ease;
}

.hero-signup:hover,
.platform-signup:hover {
text-decoration-color: #22241f;
.hero-signup:hover {
background: #d6ff7a;
box-shadow: 0 15px 36px rgb(147 194 40 / 38%);
transform: translateY(-2px);
}

.hero-signup span,
.platform-signup span {
display: inline-block;
margin-left: 4px;
.hero-signup b {
font-weight: 600;
}

.hero-signup span {
font-size: 17px;
transition: transform 150ms ease;
}

.hero-signup:hover span,
.platform-signup:hover span {
.hero-signup:hover span {
transform: translateX(3px);
}

Expand Down Expand Up @@ -2780,16 +2815,25 @@
display: none;
}

.marketing-links > a:last-of-type {
display: block;
/*
* The star count and the account button are what survive the squeeze. The
* header's copy-install pill does not: the hero repeats it one screen down,
* and a phone is rarely where that line gets pasted. Dropping it is what
* leaves room for the account button at 390px.
*/
.marketing-links > a:last-of-type,
.marketing-links > .marketing-github-link {
display: inline-flex;
align-items: center;
font-size: 11px;
}

.nav-signup {
padding: 0 15px;
}

.nav-install {
min-width: 96px;
height: 44px;
padding: 0 12px;
font-size: 11px;
display: none;
}

.marketing-hero {
Expand Down Expand Up @@ -3159,14 +3203,19 @@
font-size: 20px;
}

.marketing-links > a:last-of-type {
.marketing-links > .marketing-github-link {
display: none;
}

.hero-copy h1 {
font-size: clamp(47px, 14.8vw, 62px);
}

.hero-signup {
padding: 0 18px;
font-size: 15px;
}

.install-command code {
font-size: 9.5px;
}
Expand Down
7 changes: 5 additions & 2 deletions web/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -158,11 +158,11 @@ function renderLanding(): void {
<nav class="marketing-links" aria-label="Main navigation">
<a href="/docs/">Docs</a>
<a href="#use-cases">Use cases</a>
<a href="${SIGNUP_URL}">Web app</a>
<a class="marketing-github-link" href="${GITHUB_REPOSITORY_URL}" target="_blank" rel="noreferrer" aria-label="Star shell.online on GitHub">★ GitHub <span id="github-star-count" aria-live="polite">—</span></a>
<button class="nav-install" type="button" data-copy-target="install" data-copy-value="${installCommand}" aria-label="Copy the shell.online install command">
<span data-copy-label aria-live="polite">Copy install</span>
</button>
<a class="nav-signup" href="${SIGNUP_URL}">Sign up free</a>
</nav>
</header>

Expand All @@ -172,13 +172,16 @@ function renderLanding(): void {
<h1>Run it here.<br /><em>Open it anywhere.</em></h1>
<p class="hero-dek">Run <code>shell &lt;command&gt;</code> on your machine. It gives you a link and password to the same encrypted terminal—open it from any desktop or phone to watch or type.</p>
<div class="hero-actions">
<a class="hero-signup" href="${SIGNUP_URL}">
<b>Sign up free</b>
<span aria-hidden="true">→</span>
</a>
<button class="install-command${windowsVisitor ? " install-command-windows" : ""}" type="button" data-copy-target="install" data-copy-value="${installCommand}" aria-label="Copy install command">
<span class="command-prompt" aria-hidden="true">${installPrompt}</span>
<code>${installCommand}</code>
<span class="command-copy-label" data-copy-label aria-live="polite">Copy</span>
</button>
<div class="hero-secondary-actions">
<a class="hero-signup" href="${SIGNUP_URL}">Create an account <span aria-hidden="true">→</span></a>
<a class="text-link" href="#how">See how it works <span aria-hidden="true">↓</span></a>
</div>
</div>
Expand Down
Loading