// The popup captures that are shown to the public, in one list. // // Two surfaces read it: scripts/render-cws.mjs composes one Chrome Web Store // listing screenshot per entry marked `store`, and the frontpage gallery // shows the whole set (scripts/sync-shots.mjs copies the captures into // web/public/shots/ and writes web/src/shots.json for the page to render). // Sharing the list is the point — the store listing and substandard.blog can // never end up advertising two different builds of the popup. // // The captures themselves are real screenshots regenerated by // scripts/capture-status-docs.mjs; nothing here re-renders them. // // `caption` is placeholder copy, like the rest of the frontpage: prominent // human-facing prose is a human's call. `alt` describes what is in the image // and is not marketing, so it says what a reader who cannot see it would // otherwise miss. /** Directory the captures are regenerated into. */ export const CAPTURE_DIR = 'docs/img' /** Where the frontpage serves its copies from, and the URL prefix it uses. */ export const SITE_DIR = 'web/public/shots' export const SITE_URL_PREFIX = '/shots' /** The generated manifest the Astro page imports. */ export const MANIFEST = 'web/src/shots.json' /** * @typedef {object} Shot * @property {string} name basename in docs/img/, without the extension * @property {boolean} [store] gets its own store listing screenshot, in the * order the entries appear here * @property {string} alt what the screenshot shows * @property {string} caption placeholder frontpage copy */ /** @type {Shot[]} */ export const SHOTS = [ { name: 'popup-publication', store: true, alt: 'The substandard popup over standard.site, signed out: the account behind the publication, then the publication card with its name, description and subscriber count, a greyed-out Subscribe button, and a warning to sign in with an Atmosphere account first.', caption: 'log in with your Atmosphere account!', }, { name: 'popup-subscribed', alt: 'The substandard popup over permadeath.com, signed in: the author\u2019s account above the permablog publication card, its subscriber count, and a Subscribed button, with no warnings.', caption: 'subscribe to publications you love!', }, { name: 'popup-labeled', store: true, alt: 'The substandard popup over a placeholder publication, signed in: a red pill saying you have blocked the account it belongs to; two red moderation labels on the card, Intolerance from Bluesky’s moderation service and Platform Abuse & Manipulation from skywatch.blue, shown after asking to see the card the labels had covered; an account card reading only “Blocked user” and the handle, with no avatar or bio; the publication’s own icon, a crossed-out puppy; and a red “Subscribe anyway?” button, armed by one click.', caption: 'carry over moderation settings from other Atmosphere apps!', }, { name: 'popup-unverified', alt: 'The substandard popup over a third-party reader showing the AT Protocol blog: a warning that this page is not the publication’s verified home, linking to the real one.', caption: 'flag standard.site configuration issues!', }, ] /** Path of a shot's capture, relative to the repo root. */ export function capturePath(shot) { return `${CAPTURE_DIR}/${shot.name}.png` } /** * The shots the store listing screenshots are composed from, in listing order. * The Chrome Web Store takes at most five screenshots, and an empty listing is * a listing with no screenshots at all, so both ends fail here rather than at * upload time. */ export function storeShots(shots = SHOTS) { const store = shots.filter((shot) => shot.store) if (store.length < 1 || store.length > 5) { throw new Error(`expected 1 to 5 store shots, found ${store.length}`) } return store } /** Filename of a store shot's composed listing tile, relative to the repo root. */ export function storeTilePath(shot) { return `brand/cws/screenshot-${shot.name.replace(/^popup-/, '')}.png` }