ReviewOS

stacks/uplink

fix(homepage): the head declares no favicon and an incomplete social card

#26
Closed glennmichael123 opened this 9 days ago ·
9 days ago

Part of #6.

The page is designed for the moment someone is looking at it and for no moment after that. A tab, a bookmark, an iPhone home-screen shortcut, a Slack or iMessage unfurl and a search result are each a first impression the page never wrote any markup for, and most of the material to fix them is already sitting in the repository unreferenced. While checking which files are used, the same pass turned up sixteen files under public/ that nothing references and that the deploy serves to anyone who guesses the path.

What is there today

  • The entire link and meta block is resources/views/index.stx#L90-L107: charset, viewport, title, description, canonical, seven social tags, color-scheme, two font preconnects, the font stylesheet and the hero preload. There is no rel="icon", no rel="apple-touch-icon", no theme-color and no manifest. resources/views/404.stx#L10-L18 is the same block, shorter, with the same omissions.
  • There is no public/favicon.ico, so the browser's implicit fallback finds nothing either.
  • config/images.ts#L70 sets favicon: false under appIcons with faviconDir: 'public' at config/images.ts#L71, so the framework generates no icons on this project's behalf.
  • public/images/logos/favicon.svg and public/images/logos/favicon-dark.svg exist and are referenced nowhere under resources/, app/, config/ or routes/. Two things about them the audit did not catch: the files are byte-identical (1,606 bytes each), so favicon-dark.svg is not a dark variant of anything, and both render the Stacks "S" mark in #C14A15 on a #FFF7EC field, which is neither Uplink's mark nor Uplink's palette.
  • resources/assets/images/app-icon.png is Uplink's own mark, an amber satellite on a dark rounded square, 1024x1024, 305,562 bytes. Nothing references it. config/images.ts#L68 names an outputDir for generated app icons but the generator is off at config/images.ts#L66.
  • The social card at resources/views/index.stx#L96-L102 sets og:type, og:url, og:title, og:description, og:image, og:image:alt and twitter:card, then stops. No og:site_name, no og:locale, no og:image:width or og:image:height.
  • The declared og:image at resources/views/index.stx#L100 is /images/california-night-1920.jpg, which is the hero photo. It is 1920x1277 both in its own attributes at resources/views/index.stx#L210-L211 and on disk, so its aspect ratio is 1.50:1. Twitter, Slack, Discord and iMessage all crop a large summary card to 1.91:1, which takes roughly a fifth of the height off, top and bottom, with no say in where.
  • Neither view contains a <script type="application/ld+json"> block.
  • resources/data/release.json#L2-L5 already holds version, bytes, minimumMacOS and url, and resources/views/index.stx#L47-L50 already imports them to build the download caption.
  • The surface token the icon colours should agree with is --paper, #fafaf9 at resources/views/index.stx#L111 and #0c0c0e at resources/views/index.stx#L122.
  • Sixteen files under public/ are referenced by nothing in resources/, app/, config/ or routes/, and total 773,554 bytes against a 1.7 MB public/. images/screenshots/dashboard.png (188,733) and images/screenshots/payroll.webp (63,592) are screenshots of an unrelated product. images/screenshots/background-features.jpg (185,111), images/background-call-to-action.jpg (166,090) and images/background-faqs.jpg (75,877) are Stacks template backgrounds. images/avatars/avatar-1.png through avatar-5.png (60,091 together) are stock faces. svgs/403.svg, svgs/404.svg, svgs/500.svg and svgs/503.svg (30,848 together) illustrate framework error pages this app never serves, because config/ui.ts#L50 sets defaultViews: false and resources/views/404.stx#L2-L3 says so in its own header comment. The two Stacks logo SVGs above are the last two.

Proposal

  1. Cut the icon set from resources/assets/images/app-icon.png, which is the mark the app already ships: a 32x32 and 16x16 favicon.ico, a 180x180 apple-touch-icon.png, and an icon.svg if a vector version of that mark can be produced. Put them at the root of public/.
  2. Add to the head in resources/views/index.stx, after the canonical link at resources/views/index.stx#L95: rel="icon" pointing at the ICO, a second rel="icon" type="image/png" or type="image/svg+xml" entry if a vector exists, and rel="apple-touch-icon" at 180x180.
  3. Add the theme-color pair in the same block, #fafaf9 under media="(prefers-color-scheme: light)" and #0c0c0e under media="(prefers-color-scheme: dark)", matching --paper at resources/views/index.stx#L111 and #L122.
  4. Copy the same icon and theme-color lines into resources/views/404.stx#L10-L18.
  5. Complete the social card at resources/views/index.stx#L96-L102 with og:site_name set to Uplink, og:locale set to en_US to match lang="en" at resources/views/index.stx#L89, and og:image:width and og:image:height.
  6. Resolve the aspect ratio before declaring the dimensions. Either declare 1920 and 1277 and accept the centre crop, or cut a dedicated 1200x630 card from the same ISS photo, point og:image at it and declare 1200 and 630. The second is the better result, because a purpose-cut card can carry the product name, which a bare photograph in an unfurl does not.
  7. Add a SoftwareApplication JSON-LD block to resources/views/index.stx, reading softwareVersion, operatingSystem and downloadUrl from the release import at resources/views/index.stx#L47, with applicationCategory set to DeveloperApplication, offers at price 0 in USD, and sameAs pointing at https://github.com/stacksjs/uplink, the URL the footer already links at resources/views/index.stx#L376.
  8. Delete all sixteen unreferenced files listed above, the two Stacks logo SVGs included.

Requirements

  • Do not wire up public/images/logos/favicon.svg. The audit that produced this issue proposed it and was wrong. It is the Stacks "S", so shipping it puts the framework's logo in the tab of a product that has its own. favicon-dark.svg is the same bytes, so there is no dark variant to pair with it. Both go in the delete list.
  • One source for every icon. Derive the ICO, the apple-touch-icon and any SVG from resources/assets/images/app-icon.png so they cannot drift apart. If that file gets used, it stops being dead weight in resources/assets/.
  • The apple-touch-icon needs an opaque background. iOS composites it on the home screen with no transparency handling, so a transparent PNG gets a black square. app-icon.png already has its dark rounded square baked in, so export it flattened at 180x180 without adding a second corner radius.
  • Each theme-color carries its own media attribute. A single unqualified theme-color paints the same bar in both themes and looks broken in one of them.
  • The declared image dimensions must match the bytes actually served. If step 6 produces a new 1200x630 card, og:image, og:image:width and og:image:height all change together, and og:image:alt at resources/views/index.stx#L101 is rewritten to describe the crop rather than the full frame.
  • og:image stays an absolute URL. It is built from siteUrl at resources/views/index.stx#L15 today and must keep being, because relative URLs in Open Graph do not resolve for every consumer.
  • Read the JSON-LD values from the release import, never from literals. resources/views/index.stx#L50 already renders the same three values into the download caption, so a literal in the structured data is a second place to forget when a release ships.
  • Render the JSON-LD and parse it. stx escapes interpolated output, and a &quot; inside a ld+json block produces markup that validates as HTML and fails as JSON. Check the built page, not the template.
  • No web manifest. This is one page with no offline story and no install prompt worth having. A manifest is a fourth file to keep in sync for nothing.
  • Delete the sixteen files rather than gitignoring them. They are committed, so ignoring them leaves them in the tree and on the deploy.

Acceptance

  • curl -I https://uplink.stacksjs.com/favicon.ico returns 200 with a non-zero length, and the same for /apple-touch-icon.png.
  • The deployed home page and 404 page both show the amber satellite mark in a browser tab, and adding the site to an iPhone home screen produces that mark and not a page thumbnail.
  • The macOS menu bar tints to #fafaf9 in light mode and #0c0c0e in dark mode when the page is open in Safari, with no manual reload between theme switches.
  • resources/views/index.stx and resources/views/404.stx contain no reference to images/logos/, and git status after the delete shows sixteen removals totalling 773,554 bytes.
  • https://uplink.stacksjs.com/images/screenshots/payroll.webp and https://uplink.stacksjs.com/images/avatars/avatar-1.png both return 404.
  • Pasting the home page URL into Slack and into an iMessage thread shows a card whose image is not cropped through the subject, with the site name present.
  • The Google Rich Results test and the Schema.org validator both parse the SoftwareApplication block with no errors, and the version it reports equals the version in resources/data/release.json.
  • ./buddy lint and ./buddy typecheck pass.

Sign in to comment on this issue.