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
15 changes: 12 additions & 3 deletions packages/api/src/landing/auto-logo.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
const bands: readonly (readonly [shape: string, color: string])[] = [
['M693.161 -427.743L-623.632 1532.31L-591.107 1552.06L725.686 -407.988L693.161 -427.743Z', '#EC3F4A'],
['M745.281 -396.071L-571.511 1563.98L-538.986 1583.73L777.807 -376.315L745.281 -396.071Z', '#FF8A1D'],
['M797.394 -364.425L-519.399 1595.62L-486.874 1615.38L829.919 -344.67L797.394 -364.425Z', '#5EC72D'],
['M849.467 -332.791L-467.326 1627.26L-434.801 1647.01L881.992 -313.035L849.467 -332.791Z', '#42C3F7'],
];

const tile =
'M512.644 100H121.718C109.652 100 100 109.667 100 121.751V513.277C100 525.361 109.652 535.028 121.718 535.028H512.644C524.71 535.028 534.362 525.361 534.362 513.277V121.751C534.362 109.667 524.71 100 512.644 100Z';

Expand All @@ -8,19 +15,21 @@ const glyphs = [
'M153.33 286.339C152.848 287.306 153.33 288.272 154.537 288.272H286.776C287.742 288.272 288.465 287.306 287.983 286.339L221.863 154.139C221.381 153.172 219.933 153.172 219.45 154.139L153.33 286.339Z',
];

const coloredBands = bands.map(([band, color]) => `<path d="${band}" fill="${color}"/>`).join('');

function filled(shapes: readonly string[], fill: string): string {
return shapes.map((shape) => `<path d="${shape}" fill="${fill}"/>`).join('');
}

function iconOf(ink: string, paper: string): string {
const icon = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="100 100 435 435">${filled([tile], ink)}${filled(glyphs, paper)}</svg>`;
const icon = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 637 637">${coloredBands}${filled([tile], ink)}${filled(glyphs, paper)}</svg>`;
return `data:image/svg+xml;base64,${Buffer.from(icon).toString('base64')}`;
}

export const iconOnLight = iconOf('#1A1A1A', '#FFFFFF');

export const iconOnDark = iconOf('#FFFFFF', '#1A1A1A');

export const mark = `<svg class="logo" viewBox="100 100 435 435" role="img" aria-label="Auto"><path class="tile" d="${tile}"/>${glyphs
export const brand = `<span class="brand"><svg class="logo" viewBox="0 0 637 637" aria-hidden="true">${coloredBands}<path class="tile" d="${tile}"/>${glyphs
.map((glyph) => `<path class="glyph" d="${glyph}"/>`)
.join('')}</svg>`;
.join('')}</svg><span class="name">Auto</span></span>`;
34 changes: 34 additions & 0 deletions packages/api/src/landing/landing-page.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,13 @@ function tileOf(icon: string): string | undefined {
return /<path d="M512\.644 100H[^"]+" fill="([^"]+)"/u.exec(icon)?.[1];
}

const colorBands = ['#EC3F4A', '#FF8A1D', '#5EC72D', '#42C3F7'];

function colorsBehindTheTileOf(drawing: string): readonly string[] {
const behind = drawing.slice(0, drawing.indexOf('M512.644 100H'));
return [...behind.matchAll(/fill="([^"]+)"/gu)].map(([, color = '']: readonly string[]) => color);
}

describe('the icon of the page at the root of the server', () => {
it('is the Auto mark, dark on a light browser and light on a dark one', async () => {
const page = await (await open(createTestHandler().handler)).text();
Expand All @@ -102,6 +109,33 @@ describe('the icon of the page at the root of the server', () => {

expect(iconFor(page, 'dark')).toBe(swapped);
});

it('draws the four color bands of the Auto mark behind the tile, in both', async () => {
const page = await (await open(createTestHandler().handler)).text();

expect({
onLight: colorsBehindTheTileOf(iconFor(page, 'light')),
onDark: colorsBehindTheTileOf(iconFor(page, 'dark')),
}).toEqual({ onLight: colorBands, onDark: colorBands });
});
});

function brandOf(page: string): string {
return /<span class="brand">.*?<\/span><\/span>/su.exec(page)?.[0] ?? '';
}

describe('the brand at the head of the page at the root of the server', () => {
it('is the Auto mark, with its four color bands behind the tile', async () => {
const page = await (await open(createTestHandler().handler)).text();

expect(colorsBehindTheTileOf(brandOf(page))).toEqual(colorBands);
});

it('names Auto beside the mark', async () => {
const page = await (await open(createTestHandler().handler)).text();

expect(brandOf(page)).toMatch(/<\/svg><span class="name">Auto<\/span><\/span>$/u);
});
});

function fontsOf(page: string): readonly string[] {
Expand Down
8 changes: 4 additions & 4 deletions packages/api/src/landing/landing-page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import type { Context, MiddlewareHandler } from 'hono';
import { html, raw } from 'hono/html';

import type { ApiEnv } from '../api-env.ts';
import { mark } from './auto-logo.ts';
import { brand } from './auto-logo.ts';
import { controlPageHeaders, headOf, readOnlyPageHeaders } from './page-style.ts';
import {
act,
Expand Down Expand Up @@ -56,7 +56,7 @@ function pageOf(studioLink: string, server: Readonly<URL>, status: RuntimeStatus
</head>
<body>
<main>
${raw(mark)}
${raw(brand)}
<h1>Auto Runtime is running</h1>
<p>Create and manage your playbooks in the studio.</p>
<span class="address">${server.host}</span>
Expand All @@ -74,7 +74,7 @@ const restartingPage = html`<!doctype html>
</head>
<body>
<main>
${raw(mark)}
${raw(brand)}
<h1>Auto Runtime is restarting</h1>
<p>This page opens again once it is back.</p>
</main>
Expand All @@ -88,7 +88,7 @@ const stoppedPage = html`<!doctype html>
</head>
<body>
<main>
${raw(mark)}
${raw(brand)}
<h1>Auto Runtime has stopped</h1>
<p>Your agent starts it again when it next needs it. To start it yourself, run npx @on.auto/runtime.</p>
</main>
Expand Down
11 changes: 10 additions & 1 deletion packages/api/src/landing/page-style.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,16 @@ main {
border-radius: 20px;
text-align: center;
}
.logo { width: 52px; height: 52px; }
.brand {
display: inline-flex;
align-items: center;
gap: 0.5em;
font-size: 36px;
font-weight: 600;
letter-spacing: -0.02em;
line-height: 1;
}
.logo { width: 1.5em; height: 1.5em; }
.logo .tile { fill: var(--ink); }
.logo .glyph { fill: var(--paper); }
h1 {
Expand Down
Loading