From 99be1158d0869b9e41c946907045ba6c0bcf6df3 Mon Sep 17 00:00:00 2001 From: Zach Dunn Date: Mon, 13 Jul 2026 11:00:54 -0400 Subject: [PATCH 1/4] feat(web): single design-system pipeline foundation - BaseHead.astro: shared head baseline importing @uploads/ui/styles.css with font preloads and the shared favicon - Brand.astro: mirror Brand.tsx (ul-brand classes, var(--panel) mark fill, href/size/label props) instead of a drifted fork - one font pipeline: drop @fontsource-variable/geist{,-mono} and the duplicate checked-in Geist Pixel binary; all three woff2s now ship from packages/ui/fonts via @uploads/ui/styles.css - @uploads/ui: export ./fonts/* for preload URLs --- PRODUCT.md | 65 ++++++++++++ apps/web/package.json | 2 - apps/web/src/components/BaseHead.astro | 34 +++++++ apps/web/src/components/Brand.astro | 74 ++++++-------- apps/web/src/layouts/ErrorLayout.astro | 3 +- apps/web/src/layouts/LegalLayout.astro | 3 +- apps/web/src/pages/console.astro | 3 +- apps/web/src/pages/docs.astro | 3 +- apps/web/src/pages/github-screenshots.astro | 3 +- apps/web/src/pages/index.astro | 4 +- .../geist-pixel/GeistPixel-Variable.woff2 | Bin 39080 -> 0 bytes apps/web/src/styles/fonts/geist-pixel/OFL.txt | 93 ------------------ apps/web/src/styles/geist-pixel.css | 34 ------- packages/ui/package.json | 3 +- pnpm-lock.yaml | 16 --- 15 files changed, 136 insertions(+), 204 deletions(-) create mode 100644 PRODUCT.md create mode 100644 apps/web/src/components/BaseHead.astro delete mode 100644 apps/web/src/styles/fonts/geist-pixel/GeistPixel-Variable.woff2 delete mode 100644 apps/web/src/styles/fonts/geist-pixel/OFL.txt delete mode 100644 apps/web/src/styles/geist-pixel.css diff --git a/PRODUCT.md b/PRODUCT.md new file mode 100644 index 0000000..ca1316a --- /dev/null +++ b/PRODUCT.md @@ -0,0 +1,65 @@ +# Product + + + +## Register + +product + + + +## Users + +Developers and their coding agents. Primary user today: a single internal user (Zach) and +the agents he runs. The core workflow is CLI/agent-first: `uploads put shot.png --pr 123` +from a terminal or an agent skill, then the hosted URL lands in a GitHub PR or issue. +The web surfaces are secondary: a landing page that explains the product, and authenticated +console/account/admin pages for managing workspaces, keys, files, and galleries. + +## Product Purpose + +uploads.sh is purpose-built file hosting for putting screenshots into PRs, issues, and +agent workflows — not generic file hosting. It exists so agents (which can't drag-and-drop +into GitHub) and developers get a one-command path from local file to embeddable URL. +Success: the CLI/MCP is the product; the web app makes what you've hosted legible and +manageable; the brand makes a tiny infrastructure tool feel deliberately crafted. + +## Brand Personality + +Terminal-native, precise, quietly playful. A developer's tool that takes craft seriously — +mono-leaning typography, dark by construction, with one genuinely distinctive asset: +Geist Pixel and its variable ELSH (element-shape) axis, which should read as the brand's +signature rather than a wordmark-only garnish. Personality shows up in small, exact +moments (pixel morphs, the chevron/upload motif), never in loudness. + +## Anti-references + +- The generic "dark + purple dev tool" (Linear/Vercel-adjacent): #0a0a0b + violet accent + - Geist-for-everything is the saturated default this brand must escape. +- SaaS landing-page grammar: hero-metric blocks, identical icon-card grids, tiny uppercase + tracked eyebrows above every section, gradient text, glassmorphism. +- Generic file-hosting framing (Dropbox-alike "store anything" pitches) — the pitch is + purpose-first: PR screenshots and agent workflows. + +## Design Principles + +1. **The CLI is the hero.** Web surfaces demonstrate and manage what the CLI does; show + real commands, real output, real hosted files — not marketing abstractions. +2. **One brand, two registers.** The design system (`@uploads/ui`) is the single source of + truth; the live site and the DS must stay visually identical. +3. **Signature over decoration.** Distinctiveness comes from owned assets (Geist Pixel's + ELSH axis, the chevron/upload motif) used systematically — not from added ornament. +4. **Deliberate, not default.** Every value that survives an audit is either evolved or + explicitly kept with a recorded reason (impeccable ignore + rationale). No silent defaults. +5. **Agent-legible craft.** Pages must work without JS where possible, degrade cleanly, + and stay fast on Workers — the audience includes headless agents and curl. + +## Accessibility & Inclusion + +WCAG 2.1 AA. Dark-only palette must hold ≥4.5:1 body contrast (muted metadata text is the +known risk). Full keyboard operability on console/account/admin (file browser, forms). +`prefers-reduced-motion` alternatives for any pixel-morph/dissolve motion the brand work +adds. Touch targets ≥44px on mobile for the management surfaces. diff --git a/apps/web/package.json b/apps/web/package.json index 1531916..29bad55 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -20,8 +20,6 @@ "@astrojs/cloudflare": "^14.1.2", "@astrojs/react": "^6.0.1", "@uploads/ui": "workspace:*", - "@fontsource-variable/geist": "^5.2.9", - "@fontsource-variable/geist-mono": "^5.2.8", "astro": "^7.0.6", "files-sdk": "^2.1.0", "markdown-for-agents": "^1.3.4", diff --git a/apps/web/src/components/BaseHead.astro b/apps/web/src/components/BaseHead.astro new file mode 100644 index 0000000..381d239 --- /dev/null +++ b/apps/web/src/components/BaseHead.astro @@ -0,0 +1,34 @@ +--- +/** + * Shared baseline for every page: charset, viewport, the chevron favicon, + * the design-system stylesheet (@uploads/ui: tokens, @font-face, ul-* classes), + * and a preload for the brand mono face (the one family every surface uses). + * + * Pages own everything that varies (, CSP meta, robots/referrer, OG tags) + * and render <BaseHead /> first inside <head>. Importing the DS stylesheet here is + * the single font/token pipeline: no page should declare its own :root tokens or + * @font-face. + * + * CSP note: pages shipping a `default-src 'none'` policy need `font-src 'self'` + * (self-hosted woff2) and `style-src` including `'self'` (Astro-extracted CSS). + */ +import "@uploads/ui/styles.css"; +import geistMonoUrl from "@uploads/ui/fonts/geist-mono.woff2?url"; +import geistSansUrl from "@uploads/ui/fonts/geist.woff2?url"; + +interface Props { + /** Also preload the sans face (marketing/prose-heavy pages). */ + preloadSans?: boolean; +} + +const { preloadSans = false } = Astro.props; + +const FAVICON = + "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Crect width='32' height='32' rx='7' fill='%23121214'/%3E%3Cg fill='none' stroke='%23b794ff' stroke-width='3.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M8 12.5 L16 5 L24 12.5'/%3E%3Cpath d='M8 19.5 L16 12 L24 19.5' opacity='.55'/%3E%3Cpath d='M8 26.5 L16 19 L24 26.5' opacity='.28'/%3E%3C/g%3E%3C/svg%3E"; +--- + +<meta charset="utf-8" /> +<meta name="viewport" content="width=device-width, initial-scale=1" /> +<link rel="icon" href={FAVICON} /> +<link rel="preload" as="font" type="font/woff2" crossorigin href={geistMonoUrl} /> +{preloadSans && <link rel="preload" as="font" type="font/woff2" crossorigin href={geistSansUrl} />} diff --git a/apps/web/src/components/Brand.astro b/apps/web/src/components/Brand.astro index c30c025..ce8884e 100644 --- a/apps/web/src/components/Brand.astro +++ b/apps/web/src/components/Brand.astro @@ -1,60 +1,44 @@ --- /** - * Canonical uploads.sh brand lockup: the stacked-chevron mark + the "uploads.sh" - * wordmark set in Geist Pixel, linking home. This is the single source of truth — - * every page's top-left brand should render <Brand />, not its own markup, so the - * homepage treatment stays identical everywhere. + * Astro mirror of the design system's Brand component (packages/ui/src/Brand.tsx). + * The DS is the source of truth; this file must stay markup-identical to Brand.tsx + * (same .ul-brand classes, same SVG) so the lockup renders the same everywhere + * without hydrating React for a static element. If Brand.tsx changes, change this. * - * Importing the pixel face here means any page that drops in <Brand /> gets the - * font wired up with no extra import. Colors read the page's --fg / --accent - * tokens (with the homepage literals as fallbacks) so the mark fits each surface. + * Styling comes from @uploads/ui/styles.css (.ul-brand), imported here so any page + * that drops in <Brand /> gets the tokens, classes, and Geist Pixel face wired up. * * CSP note: pages under a `default-src 'none'` policy must add `font-src 'self'` * so the self-hosted woff2 can load. */ -import "../styles/geist-pixel.css"; +import "@uploads/ui/styles.css"; + +interface Props { + /** Link target for the lockup. Defaults to `/`. Pass `null` to render a non-link. */ + href?: string | null; + /** `"lg"` renders the larger homepage-hero treatment. */ + size?: "md" | "lg"; + /** Wordmark text. Defaults to the canonical `uploads.sh`. */ + label?: string; +} + +const { href = "/", size = "md", label = "uploads.sh" } = Astro.props; +const cls = ["ul-brand", size === "lg" && "ul-brand--lg"].filter(Boolean).join(" "); +const Tag = href == null ? "span" : "a"; +const attrs = + href == null + ? { class: cls, "aria-label": `${label} brand` } + : { class: cls, href, "aria-label": `${label} home` }; --- -<a class="brand" href="/" aria-label="uploads.sh home"> - <svg viewBox="0 0 32 32" aria-hidden="true"> - <rect width="32" height="32" rx="7" fill="#121214"></rect> +<Tag {...attrs}> + <svg class="ul-brand__mark" viewBox="0 0 32 32" aria-hidden="true"> + <rect width="32" height="32" rx="7" fill="var(--panel, #121214)"></rect> <g fill="none" stroke="var(--accent, #b794ff)" stroke-width="3.2" stroke-linecap="round" stroke-linejoin="round"> <path d="M8 12.5 L16 5 L24 12.5"></path> <path d="M8 19.5 L16 12 L24 19.5" opacity=".55"></path> <path d="M8 26.5 L16 19 L24 26.5" opacity=".28"></path> </g> </svg> - <span>uploads.sh</span> -</a> - -<style> - .brand { - display: inline-flex; - align-items: center; - gap: 9px; - color: var(--fg, #ececea); - text-decoration: none; - font-family: "Geist Pixel", "Geist Mono Variable", ui-monospace, monospace; - font-variation-settings: "ELSH" var(--pixel-shape, 1); - font-size: 15px; - letter-spacing: 0.04em; - line-height: 1; - white-space: nowrap; - } - .brand svg { - width: 20px; - height: 20px; - border-radius: 5px; - flex: none; - } - .brand:hover, - .brand:focus-visible { - color: var(--fg, #ececea); - outline: none; - } - .brand:focus-visible { - outline: 2px solid var(--accent, #b794ff); - outline-offset: 3px; - border-radius: 3px; - } -</style> + <span>{label}</span> +</Tag> diff --git a/apps/web/src/layouts/ErrorLayout.astro b/apps/web/src/layouts/ErrorLayout.astro index 60b7b1a..098bec6 100644 --- a/apps/web/src/layouts/ErrorLayout.astro +++ b/apps/web/src/layouts/ErrorLayout.astro @@ -3,8 +3,7 @@ * Shared shell for Astro status pages (404 missing route, 500 application error). * Same flat panel + titlebar treatment as the landing terminal. */ -import "@fontsource-variable/geist/index.css"; -import "@fontsource-variable/geist-mono/index.css"; +import "@uploads/ui/styles.css"; import Brand from "../components/Brand.astro"; import Footer from "../components/Footer.astro"; diff --git a/apps/web/src/layouts/LegalLayout.astro b/apps/web/src/layouts/LegalLayout.astro index b2b216e..1dfaf91 100644 --- a/apps/web/src/layouts/LegalLayout.astro +++ b/apps/web/src/layouts/LegalLayout.astro @@ -1,8 +1,7 @@ --- // Shared shell for the static legal pages (/terms, /privacy). Same flat dark // palette and Geist type as the landing page, tuned for long-form prose. -import "@fontsource-variable/geist/index.css"; -import "@fontsource-variable/geist-mono/index.css"; +import "@uploads/ui/styles.css"; import Brand from "../components/Brand.astro"; import Footer from "../components/Footer.astro"; diff --git a/apps/web/src/pages/console.astro b/apps/web/src/pages/console.astro index 9893c91..c700f77 100644 --- a/apps/web/src/pages/console.astro +++ b/apps/web/src/pages/console.astro @@ -1,8 +1,7 @@ --- // Minimal operator console: paste a bearer token, list usage + files via the public API. // No server-side secrets — token stays in the browser. Scaffold toward a fuller files-sdk UI. -import "@fontsource-variable/geist/index.css"; -import "@fontsource-variable/geist-mono/index.css"; +import "@uploads/ui/styles.css"; import { env } from "cloudflare:workers"; import { resolveConsoleMode } from "../lib/console-mode"; import Brand from "../components/Brand.astro"; diff --git a/apps/web/src/pages/docs.astro b/apps/web/src/pages/docs.astro index abbb329..6415851 100644 --- a/apps/web/src/pages/docs.astro +++ b/apps/web/src/pages/docs.astro @@ -2,8 +2,7 @@ // uploads.sh — docs. A single linkable page that walks through the same setup // the GitHub README covers, in plain language with click-to-copy commands. // Purpose-first: getting media onto GitHub PRs, issues, and code reviews. -import "@fontsource-variable/geist/index.css"; -import "@fontsource-variable/geist-mono/index.css"; +import "@uploads/ui/styles.css"; import AuthIndicator from "../components/AuthIndicator.astro"; import Brand from "../components/Brand.astro"; import Footer from "../components/Footer.astro"; diff --git a/apps/web/src/pages/github-screenshots.astro b/apps/web/src/pages/github-screenshots.astro index 32675d5..57b333b 100644 --- a/apps/web/src/pages/github-screenshots.astro +++ b/apps/web/src/pages/github-screenshots.astro @@ -3,8 +3,7 @@ // agents (Claude Code, Codex, CI jobs, scripts) to upload screenshots and // video to GitHub PRs and issues. Prose targets the search question directly; // FAQ JSON-LD mirrors the on-page answers. -import "@fontsource-variable/geist/index.css"; -import "@fontsource-variable/geist-mono/index.css"; +import "@uploads/ui/styles.css"; import Brand from "../components/Brand.astro"; import Footer from "../components/Footer.astro"; diff --git a/apps/web/src/pages/index.astro b/apps/web/src/pages/index.astro index 622fa97..3b93da5 100644 --- a/apps/web/src/pages/index.astro +++ b/apps/web/src/pages/index.astro @@ -1,9 +1,7 @@ --- // uploads.sh — landing. Beats: headline + star CTA, the real two-command demo, // the GitHub comment it produces, what else it does, and copyable setup rows. -import "@fontsource-variable/geist/index.css"; -import "@fontsource-variable/geist-mono/index.css"; -import "../styles/geist-pixel.css"; +import "@uploads/ui/styles.css"; import AuthIndicator from "../components/AuthIndicator.astro"; import Brand from "../components/Brand.astro"; import Footer from "../components/Footer.astro"; diff --git a/apps/web/src/styles/fonts/geist-pixel/GeistPixel-Variable.woff2 b/apps/web/src/styles/fonts/geist-pixel/GeistPixel-Variable.woff2 deleted file mode 100644 index 0dece33c457b833cc1a5a838710e8f225ac0915b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 39080 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 diff --git a/apps/web/src/styles/fonts/geist-pixel/OFL.txt b/apps/web/src/styles/fonts/geist-pixel/OFL.txt deleted file mode 100644 index 999fa23..0000000 --- a/apps/web/src/styles/fonts/geist-pixel/OFL.txt +++ /dev/null @@ -1,93 +0,0 @@ -Copyright 2026 The Geist Project Authors (https://github.com/vercel/geist-font) - -This Font Software is licensed under the SIL Open Font License, Version 1.1. -This license is copied below, and is also available with a FAQ at: -https://openfontlicense.org - - ------------------------------------------------------------ -SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 ------------------------------------------------------------ - -PREAMBLE -The goals of the Open Font License (OFL) are to stimulate worldwide -development of collaborative font projects, to support the font creation -efforts of academic and linguistic communities, and to provide a free and -open framework in which fonts may be shared and improved in partnership -with others. - -The OFL allows the licensed fonts to be used, studied, modified and -redistributed freely as long as they are not sold by themselves. The -fonts, including any derivative works, can be bundled, embedded, -redistributed and/or sold with any software provided that any reserved -names are not used by derivative works. The fonts and derivatives, -however, cannot be released under any other type of license. The -requirement for fonts to remain under this license does not apply -to any document created using the fonts or their derivatives. - -DEFINITIONS -"Font Software" refers to the set of files released by the Copyright -Holder(s) under this license and clearly marked as such. This may -include source files, build scripts and documentation. - -"Reserved Font Name" refers to any names specified as such after the -copyright statement(s). - -"Original Version" refers to the collection of Font Software components as -distributed by the Copyright Holder(s). - -"Modified Version" refers to any derivative made by adding to, deleting, -or substituting -- in part or in whole -- any of the components of the -Original Version, by changing formats or by porting the Font Software to a -new environment. - -"Author" refers to any designer, engineer, programmer, technical -writer or other person who contributed to the Font Software. - -PERMISSION & CONDITIONS -Permission is hereby granted, free of charge, to any person obtaining -a copy of the Font Software, to use, study, copy, merge, embed, modify, -redistribute, and sell modified and unmodified copies of the Font -Software, subject to the following conditions: - -1) Neither the Font Software nor any of its individual components, -in Original or Modified Versions, may be sold by itself. - -2) Original or Modified Versions of the Font Software may be bundled, -redistributed and/or sold with any software, provided that each copy -contains the above copyright notice and this license. These can be -included either as stand-alone text files, human-readable headers or -in the appropriate machine-readable metadata fields within text or -binary files as long as those fields can be easily viewed by the user. - -3) No Modified Version of the Font Software may use the Reserved Font -Name(s) unless explicit written permission is granted by the corresponding -Copyright Holder. This restriction only applies to the primary font name as -presented to the users. - -4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font -Software shall not be used to promote, endorse or advertise any -Modified Version, except to acknowledge the contribution(s) of the -Copyright Holder(s) and the Author(s) or with their explicit written -permission. - -5) The Font Software, modified or unmodified, in part or in whole, -must be distributed entirely under this license, and must not be -distributed under any other license. The requirement for fonts to -remain under this license does not apply to any document created -using the Font Software. - -TERMINATION -This license becomes null and void if any of the above conditions are -not met. - -DISCLAIMER -THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT -OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE -COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL -DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM -OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/apps/web/src/styles/geist-pixel.css b/apps/web/src/styles/geist-pixel.css deleted file mode 100644 index c742e3b..0000000 --- a/apps/web/src/styles/geist-pixel.css +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Geist Pixel — Vercel's pixel display face, self-hosted as a VARIABLE font. - * - * Source: the official variable download from https://vercel.com/font?type=pixel - * (SIL OFL 1.1 — see fonts/geist-pixel/OFL.txt). The single .ttf was converted to - * woff2 (~39KB) for the web; it carries every style plus all intermediates. - * - * One custom axis — ELSH ("Element Shape"), 0–100 — morphs the shape of each - * "pixel". The named instances sit at these values; any value between them is - * also valid (that's the point of shipping the variable font): - * - * 0 Regular 40 Grid - * 1 Square 60 Triangle - * 20 Circle 80 Line - * - * Set the shape per element with `font-variation-settings: "ELSH" <n>`, or lean - * on the --pixel-shape token below, which every pixel usage reads with a Square - * (1) default. Change --pixel-shape on a scope to restyle the pixels there. - * - * Vite fingerprints the relative url() and emits it under /_astro. - */ - -@font-face { - font-family: "Geist Pixel"; - src: url("./fonts/geist-pixel/GeistPixel-Variable.woff2") format("woff2"); - font-weight: 400; - font-style: normal; - font-display: swap; -} - -:root { - /* Element Shape (ELSH) default for the pixel face — 1 = Square. */ - --pixel-shape: 1; -} diff --git a/packages/ui/package.json b/packages/ui/package.json index d7f1e3b..ec3febf 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -17,7 +17,8 @@ "import": "./dist/index.js" }, "./styles.css": "./dist/uploads-ui.css", - "./tokens.css": "./src/tokens.css" + "./tokens.css": "./src/tokens.css", + "./fonts/*": "./fonts/*" }, "files": [ "dist", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ca00ae0..fde3653 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -134,12 +134,6 @@ importers: '@astrojs/react': specifier: ^6.0.1 version: 6.0.1(@types/node@26.1.0)(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(esbuild@0.28.1)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(yaml@2.9.0) - '@fontsource-variable/geist': - specifier: ^5.2.9 - version: 5.2.9 - '@fontsource-variable/geist-mono': - specifier: ^5.2.8 - version: 5.2.8 '@uploads/ui': specifier: workspace:* version: link:../../packages/ui @@ -1230,12 +1224,6 @@ packages: cpu: [x64] os: [win32] - '@fontsource-variable/geist-mono@5.2.8': - resolution: {integrity: sha512-KI5bj+hkkRiHttYHmccotUZ80ZuZyai+RwI1d7UId0clkx/jXxlo8qYK8j54WzmpBjtMoEMPyllV7faDcj+6RA==} - - '@fontsource-variable/geist@5.2.9': - resolution: {integrity: sha512-TP+QSBG3wxKGPE33CbMy/L0Nu3qvJ6Fy81Yc4LnQ95xH+i+cfEp8fyU8/kfV14YwszxIFPhnoMTbjL71waVpyQ==} - '@hono/node-server@1.19.14': resolution: {integrity: sha512-GwtvgtXxnWsucXvbQXkRgqksiH2Qed37H9xHZocE5sA3N8O8O8/8FA3uclQXxXVzc9XBZuEOMK7+r02FmSpHtw==} engines: {node: '>=18.14.1'} @@ -5770,10 +5758,6 @@ snapshots: '@esbuild/win32-x64@0.28.1': optional: true - '@fontsource-variable/geist-mono@5.2.8': {} - - '@fontsource-variable/geist@5.2.9': {} - '@hono/node-server@1.19.14(hono@4.12.28)': dependencies: hono: 4.12.28 From 7605fbbdccdc74f7cb8b3107514c2791042303e2 Mon Sep 17 00:00:00 2001 From: Zach Dunn <zach@rally.space> Date: Mon, 13 Jul 2026 11:07:56 -0400 Subject: [PATCH 2/4] refactor(web): consume @uploads/ui tokens on every page Replace 11 hand-copied :root token blocks and per-page favicon/meta boilerplate with the shared BaseHead component. Canonicalize renamed tokens (--ok/--green-ok to --green, --danger to --red, --purple to --accent, --bezel to --line, --cyan to --body, --purple-dim to --muted) and swap radius literals matching DS tokens to var(--radius-*). Intended visual fixes riding along: auth + admin surfaces now actually load Geist Mono Variable (was declared but never loaded), and the public gallery pages get the brand font stacks back. --- apps/web/src/layouts/ErrorLayout.astro | 26 ++----- apps/web/src/layouts/LegalLayout.astro | 20 +----- .../src/pages/accept-invitation/[id].astro | 17 ++--- apps/web/src/pages/account.astro | 23 +++---- apps/web/src/pages/admin.astro | 21 +++--- apps/web/src/pages/console.astro | 27 ++------ apps/web/src/pages/device.astro | 19 ++---- apps/web/src/pages/docs.astro | 67 +++++++------------ apps/web/src/pages/g/[id].astro | 11 ++- apps/web/src/pages/g/[id]/[item].astro | 13 ++-- apps/web/src/pages/github-screenshots.astro | 31 ++------- apps/web/src/pages/index.astro | 37 +++------- apps/web/src/pages/invite.astro | 9 +-- apps/web/src/pages/login.astro | 17 ++--- 14 files changed, 101 insertions(+), 237 deletions(-) diff --git a/apps/web/src/layouts/ErrorLayout.astro b/apps/web/src/layouts/ErrorLayout.astro index 098bec6..3249cbf 100644 --- a/apps/web/src/layouts/ErrorLayout.astro +++ b/apps/web/src/layouts/ErrorLayout.astro @@ -3,7 +3,7 @@ * Shared shell for Astro status pages (404 missing route, 500 application error). * Same flat panel + titlebar treatment as the landing terminal. */ -import "@uploads/ui/styles.css"; +import BaseHead from "../components/BaseHead.astro"; import Brand from "../components/Brand.astro"; import Footer from "../components/Footer.astro"; @@ -16,33 +16,15 @@ interface Props { } const { status, title, message, hint } = Astro.props; - -const FAVICON = - "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Crect width='32' height='32' rx='7' fill='%23121214'/%3E%3Cg fill='none' stroke='%23b794ff' stroke-width='3.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M8 12.5 L16 5 L24 12.5'/%3E%3Cpath d='M8 19.5 L16 12 L24 19.5' opacity='.55'/%3E%3Cpath d='M8 26.5 L16 19 L24 26.5' opacity='.28'/%3E%3C/g%3E%3C/svg%3E"; --- <html lang="en"> <head> - <meta charset="utf-8" /> - <meta name="viewport" content="width=device-width, initial-scale=1" /> + <BaseHead /> <meta name="robots" content="noindex, nofollow, noarchive" /> <meta name="description" content={`${status} ${title} — uploads.sh`} /> <title>{status} · {title} · uploads.sh - diff --git a/apps/web/src/pages/login.astro b/apps/web/src/pages/login.astro index 8a2ff25..b76a888 100644 --- a/apps/web/src/pages/login.astro +++ b/apps/web/src/pages/login.astro @@ -5,6 +5,7 @@ import { CF_RUM_SCRIPT_SRC, STYLE_SRC_SELF_AND_INLINE, } from "../lib/csp"; +import BaseHead from "../components/BaseHead.astro"; import Brand from "../components/Brand.astro"; import Footer from "../components/Footer.astro"; @@ -27,40 +28,34 @@ const csp = [ "form-action 'none'", "frame-ancestors 'none'", ].join("; "); - -const FAVICON = - "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Crect width='32' height='32' rx='7' fill='%23121214'/%3E%3Cg fill='none' stroke='%23b794ff' stroke-width='3.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M8 12.5 L16 5 L24 12.5'/%3E%3Cpath d='M8 19.5 L16 12 L24 19.5' opacity='.55'/%3E%3Cpath d='M8 26.5 L16 19 L24 26.5' opacity='.28'/%3E%3C/g%3E%3C/svg%3E"; --- - - + Sign in · uploads.sh - @@ -87,6 +88,7 @@ const title = item && gallery ? `${item.filename} · ${gallery.title} · uploads {gallery && item ? ( <> +

{item.filename}

{gallery.title} · {index + 1} of {items.length}
diff --git a/apps/web/src/pages/index.astro b/apps/web/src/pages/index.astro index 90b57dd..91fe863 100644 --- a/apps/web/src/pages/index.astro +++ b/apps/web/src/pages/index.astro @@ -61,9 +61,13 @@ const authOrigin = import.meta.env.PUBLIC_UPLOADS_AUTH_ORIGIN ?? "https://auth.u .top { display: flex; align-items: center; + flex-wrap: wrap; gap: 12px; margin-bottom: 6px; } + @media (max-width: 420px) { + .star-cta .count { display: none; } + } .star-cta { margin-left: auto; display: inline-flex; @@ -393,7 +397,7 @@ const authOrigin = import.meta.env.PUBLIC_UPLOADS_AUTH_ORIGIN ?? "https://auth.u
install npm install -g @buildinternet/uploads - +
@@ -462,7 +466,7 @@ const authOrigin = import.meta.env.PUBLIC_UPLOADS_AUTH_ORIGIN ?? "https://auth.u
-

# what else it does

+

# what else it does

one managed comment

@@ -515,27 +519,27 @@ const authOrigin = import.meta.env.PUBLIC_UPLOADS_AUTH_ORIGIN ?? "https://auth.u

-

# get set up — click to copy

+

# get set up — click to copy

cli npm install -g @buildinternet/uploads && uploads login - +
agents uploads install - +
skill npx skills add buildinternet/uploads --skill uploads-cli - +
mcp claude mcp add --transport http uploads https://agents.uploads.sh/mcp - +

diff --git a/apps/web/src/pages/invite.astro b/apps/web/src/pages/invite.astro index b189703..c63d380 100644 --- a/apps/web/src/pages/invite.astro +++ b/apps/web/src/pages/invite.astro @@ -42,8 +42,8 @@ const csp = [

Checking your invite…

Treat this link like a password — it's single-use and stops working once you log in.

diff --git a/apps/web/src/pages/login.astro b/apps/web/src/pages/login.astro index b76a888..61a0c64 100644 --- a/apps/web/src/pages/login.astro +++ b/apps/web/src/pages/login.astro @@ -55,7 +55,7 @@ const csp = [ label{display:grid;gap:6px;color:var(--muted);font-size:10.5px;letter-spacing:.1em;text-transform:uppercase} input{background:var(--bg);border:1px solid var(--line);border-radius:var(--radius-md);color:var(--fg);padding:10px 12px;font:14px var(--mono)} input:focus-visible{border-color:var(--accent);outline:none} - button[type=submit]{font:12px var(--mono);letter-spacing:.04em;color:var(--accent);background:var(--bg);border:1px solid var(--line);border-radius:var(--radius-sm);padding:10px 13px;cursor:pointer} + button[type=submit]{font:12px var(--mono);letter-spacing:.04em;color:var(--accent);background:var(--bg);border:1px solid var(--line);border-radius:var(--radius-sm);padding:12px 14px;cursor:pointer} button[type=submit]:hover,button[type=submit]:focus-visible{border-color:var(--accent);outline:none} button:disabled{opacity:.6;cursor:default} [hidden]{display:none!important} diff --git a/packages/ui/src/Callout.tsx b/packages/ui/src/Callout.tsx index 047ceef..2d32101 100644 --- a/packages/ui/src/Callout.tsx +++ b/packages/ui/src/Callout.tsx @@ -23,7 +23,7 @@ export function Callout({ tone = "info", title, className, children, ...rest }: .filter(Boolean) .join(" "); return ( -
+
{title != null && {title}} {children}
diff --git a/packages/ui/src/Field.tsx b/packages/ui/src/Field.tsx index ceeb9a2..32f9961 100644 --- a/packages/ui/src/Field.tsx +++ b/packages/ui/src/Field.tsx @@ -1,4 +1,11 @@ -import type { ComponentPropsWithoutRef, ReactNode } from "react"; +import { + cloneElement, + isValidElement, + useId, + type ComponentPropsWithoutRef, + type ReactElement, + type ReactNode, +} from "react"; export interface InputProps extends ComponentPropsWithoutRef<"input"> {} @@ -39,6 +46,12 @@ export interface FieldProps extends ComponentPropsWithoutRef<"div"> { invalid?: boolean; /** The control — typically an `Input`. */ children?: ReactNode; + /** + * id of the control this label describes. Defaults to a generated id (via + * `useId`) that is cloned onto the child control when it doesn't already + * have one. + */ + id?: string; } /** @@ -54,12 +67,29 @@ export interface FieldProps extends ComponentPropsWithoutRef<"div"> { * * */ -export function Field({ label, hint, invalid = false, className, children, ...rest }: FieldProps) { +export function Field({ + label, + hint, + invalid = false, + className, + children, + id, + ...rest +}: FieldProps) { const cls = ["ul-field", invalid && "ul-field--invalid", className].filter(Boolean).join(" "); + const generatedId = useId(); + const hasLabel = label != null; + const childElement = isValidElement<{ id?: string }>(children) ? children : null; + const existingChildId = childElement?.props.id; + const controlId = id ?? existingChildId ?? generatedId; + const control = + hasLabel && childElement && !existingChildId + ? cloneElement(childElement as ReactElement<{ id?: string }>, { id: controlId }) + : children; return (
- {label != null && {label}} - {children} + {hasLabel && } + {control} {hint != null && {hint}}
); diff --git a/packages/ui/src/FileBrowser.tsx b/packages/ui/src/FileBrowser.tsx index 4a13d4c..7e2bdf0 100644 --- a/packages/ui/src/FileBrowser.tsx +++ b/packages/ui/src/FileBrowser.tsx @@ -94,13 +94,22 @@ export function FileBrowser({ return (