Skip to content

Console PWA manifest: declare the branded icon's real type and offer 192/512 PNG icons so a branded Console stays installable #29332

Closed

Description

@hotlong

Context

This was found in the acceptance review of #29326 (card #29155). It predates that PR: main has the same code.

The Console's web app manifest declares its icon as type: 'image/svg+xml', sizes: 'any' (ui/apps/console/src/main.tsx, the manifest block). The favicon <link> a few lines earlier already tells SVG from PNG.

When Setup branding sets a PNG or ICO favicon, the manifest mis-declares it. Such a favicon is also likely below Chrome's 144 px minimum for the install prompt. So a branded Console may not be installable, although card #29155 asks for the branded icon.

Ask

  1. Derive the manifest icon type and sizes from the configured branding asset, as the favicon link does.
  2. When the branded asset is not SVG and not at least 192 px, add 192 px and 512 px PNG icons to the manifest. Use the platform default icons, or a server-rendered resize if one exists. Say which in the PR.
  3. Keep start_url and scope as they are.

Acceptance

  • A unit test covers the manifest for SVG, PNG and ICO branding, and for no branding.
  • A Playwright or CDP reading shows no manifest installability errors with a PNG favicon configured.

Activity

  1. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    Contributor

    triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U

    Path: none

    Triage: p3 kept · pm:queue · 2026-11-02T13:02Z

    ⛔ Not a claim.

    • Read fresh. The Console PWA manifest declares any branded icon as SVG, so a PNG or ICO branding can break installability. p3 kept. The card had no state (H13).

    Generated by Claude Code

  2. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    Contributor

    domain:ui#3 · zhuangjianguo · session_01QsR2jV4dWohojjbTJTQq5m

    ⛔ Not a claim. Reserved by domain:ui#3 (assignee set; pm:queue kept), agreed with domain:ui#4. This card edits the Console manifest block in ui/apps/console/src/main.tsx, which PR #29326 (#29155, Tier H, awaiting the maintainer) also rewrites, so the seat dispatches it after PR #29326 lands and keeps that PR's absolute start_url, scope and icon URLs as Ask 3 says.

  3. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    Contributor

    domain:ui#3 · zhuangjianguo · session_01QsR2jV4dWohojjbTJTQq5m

    Claim: PM loop round 17 · 2026-11-02T13:44Z
    Session: session_01QsR2jSqNEXXfJECHQqN7mG (card thread, os-dev); dispatched by seat session session_01QsR2jV4dWohojjbTJTQq5m
    Account: zhuangjianguo
    Branch: claude/project-thread-vmwtew (platform-assigned to the card thread; it can push only this branch)
    Worktree: objectstack-issue-29332
    Domain: domain:ui
    Seat: domain:ui#3
    File surface: ui/apps/console/src/main.tsx (the manifest block), a small console-local helper beside it for the icon entries, default icon assets under ui/apps/console/public only if new PNG sizes must be added (named in the report first), their tests, and a changeset (stop on breach; explain in the report). @object-ui/mobile (generatePWAManifest) is out of surface.
    Container & model: S, mode:thread, model: default tier (dispatch-gates --tier: no path-derived mandate), effort: high
    Clause-②: no
    Metadata-protocol: none
    Responsibility: open — recorded at review
    Thread-read: 6577820333
    Premise: holds (at origin/main 838a802b: ui/apps/console/src/main.tsx builds the runtime manifest through generatePWAManifest with every icon declared sizes: 'any', type: 'image/svg+xml' (~:177-178), while the favicon link at ~:146 already tells SVG from PNG; ui/apps/console/public holds only favicon.svg).
    Serial constraints cleared: PR #29326 (#29155) landed as b7720782, as agreed with domain:ui#4; its absolute start_url, scope and icon URLs stay as they are. No in-flight claim of seats 1-5 names ui/apps/console/src/main.tsx.

  4. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    Contributor

    domain:ui#3 · zhuangjianguo · session_01QsR2jSqNEXXfJECHQqN7mG
    os-dev-report

    {
      "issue": 29332,
      "status": "done",
      "branch": "claude/project-thread-vmwtew",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/29405",
      "head": "1b6eb74f",
      "session": "session_01QsR2jSqNEXXfJECHQqN7mG",
      "premise_still_valid": true,
      "summary": "The Console runtime manifest icons are built by a console-local helper (ui/apps/console/src/pwaManifestIcons.ts): SVG or no branding keeps one image/svg+xml 'any' entry; a raster favicon (PNG, ICO, WebP, JPEG, GIF, AVIF) declares its own MIME type and its measured WIDTHxHEIGHT, and is left out when its type is unknown or it cannot be measured (error, zero size, 10 s timeout). Without a square raster of at least 192 px, the new platform defaults public/icon-192.png and icon-512.png (rendered from public/favicon.svg with Chromium; seat approved before adding) are appended. main.tsx removes the static manifest synchronously as before and injects the Blob manifest from injectPwaManifest without await, so the measurement never holds first paint; start_url, scope and absolute icon URLs unchanged. @object-ui/mobile untouched.",
      "tests": "pnpm --dir ui exec vitest run apps/console/src/pwaManifestIcons.test.ts: 23/23 passed (at 29065950 and again at 1b6eb74f). Ablation via scripts/ablation-replace.mjs, anchor 'const type = iconTypeOf(src);' -> 'const type: string | undefined = SVG_TYPE;' (anchor 1->0, replacement 0->1, blob 12d7f20e -> 2837356e): 6 failed / 17 passed (small PNG, large PNG, non-square PNG, ICO, unmeasurable, unknown type red; none and SVG green); restored, blob equals HEAD, git diff HEAD empty. turbo run type-check --filter=@object-ui/console: 71/71. eslint on the three ts/tsx files: exit 0. CDP installability (full Chromium, launchPersistentContext channel chromium, vite build served under /console/ with base tag, stubbed /api/v1/runtime/config): before (main manifest block) 32 px PNG -> installabilityErrors no-acceptable-icon (minimum-icon-size-in-pixels 144); after -> [] with icons 32x32 PNG + 192x192 + 512x512; 256 px PNG, SVG and none -> [] both sides. Probe script: /mnt/project-files/issue-29332/installability-probe.mjs.",
      "gates": "dispatch-gates --commands at 29065950: 33 derived, 33 run, all exit 0 (incl. check-sdui-manifest exit 0, pnpm --dir ui exec vitest run scripts/ 169 passed 2 skipped files, lock VERDICT command-exit 0); --ran reconciliation: 0 NOT-MEASURED, 0 UNRUN. PR-body gates on the final body: check-changeset-no-major 0, check-adr-0087-registration 0, check-closing-keyword-parity 0, check-partof-closing-keyword 0. ui check:new-line-citations: 0 new. CI check-runs: in_progress at report time (re-runs are the seat's).",
      "line_budget": "card size S; diff vs main +339/-30 over 6 files (2 binary PNGs counted 0): helper 134, test 163, main.tsx +32/-30, changeset 10. Under the 3000 human-merge threshold.",
      "files_changed": [
        ".changeset/29332-console-pwa-manifest-icons.md",
        "ui/apps/console/public/icon-192.png",
        "ui/apps/console/public/icon-512.png",
        "ui/apps/console/src/main.tsx",
        "ui/apps/console/src/pwaManifestIcons.ts",
        "ui/apps/console/src/pwaManifestIcons.test.ts"
      ],
      "deviations": [
        "Unknown-type and unmeasurable raster favicons are left out of the manifest (defaults stand in) rather than declared image/png, because generatePWAManifest defaults a missing type to image/png and @object-ui/mobile is out of surface.",
        "Full dogfood battery not run: no ! in the title and Clause-② carries no (narrowing) arm."
      ],
      "dogfood_battery": "n/a — no `!` in the PR title and no (narrowing) arm",
      "mcp_calls": "4 — mcp__github__issue_read x3 (get, get_comments x2), mcp__claude-code-remote__get_session x1; no GitHub MCP write",
      "api_writes": "2 — relay pr_create (PR 29405), this report via post-stamped; plus git push (not REST)",
      "open_questions": [],
      "security_findings": "none",
      "out_of_scope_findings": [
        "carrier: none · noted in PR Acceptance notes, not filed: the favicon link in main.tsx and index.html labels every non-SVG favicon image/png (ICO included); browsers sniff favicon bytes, nothing visible follows."
      ]
    }
  5. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    Contributor

    domain:ui#3 · zhuangjianguo · session_01QsR2jV4dWohojjbTJTQq5m

    Landed: PR #29405 merged at 2026-11-02T14:46Z as 1d03901c. Fixes #29332 closed this card; pm:dispatched removed. Delivered: the Console's runtime PWA manifest declares a raster branding favicon with its real MIME type and measured size, keeps the single SVG any entry for an SVG or default favicon, and adds the default icon-192.png / icon-512.png whenever no square raster of at least 192 px is present, so a small PNG branding installs (Chrome no-acceptable-icon gone). The manifest lands after measurement, off the first-paint path. Nothing left on this card.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions