Skip to content

hosting/photo-storage broken on static-site recipe — revert to asset-canister interim, decide long-term fate #1459

Closed

Description

@marc0olo

Part of #1458.

hosting/photo-storage demonstrates programmatic uploads via AssetManager from @icp-sdk/canisters/assets. Since #1449 switched it to @dfinity/static-site, the example is broken at runtime: the certified-assets canister exposes none of the legacy API (list, store, create_batch, commit_batch — verified against certified-assets.did). App.jsx calls assetManager.list() on page load, so the app fails immediately. Only authorize coincidentally still resolves (certified-assets has a flat authorize model), masking the breakage.

Rewriting against the new interface is not viable: certified-assets mutations go through a single-session start_sync/upload_chunks/execute_operations protocol that is version-locked to the recipe's sync plugin and designed for deploys, not concurrent end-user uploads.

Interim fix (unblocks the example now): revert the recipe to @dfinity/asset-canister@v2.2.1 — the only canister supporting the AssetManager flow — with a comment explaining the deliberate exception, and verify the app works end-to-end again.

Long-term decision:

  • (a) keep it permanently on the legacy recipe as the programmatic-uploads example, clearly labeled;
  • (b) repurpose it to store photos in a purpose-built backend canister (overlaps with rust/photo_gallery);
  • (c) retire it.

Depends on whether the legacy asset canister remains supported (icskills#256 keeps it as documented legacy) and whether a runtime-upload story exists/is planned for certified-assets.

Activity

  1. marc0olo commented on Jul 30, 2026

    @marc0olo
    ContributorAuthor

    Status: the interim revert is applied locally and will land with the next batch of commits:

    • icp.yaml recipe reverted to @dfinity/asset-canister@v2.2.1 with a comment explaining the deliberate exception (so the next repo-wide recipe sweep doesn't silently re-migrate it).
    • Bonus fix found on the way: the README's authorize command targeted a canister named photo-storage, but the canister is named frontend in icp.yaml — the documented command could never have worked. Corrected to icp canister call frontend authorize ....

    Remaining in this issue:

    • Manual e2e verification of the reverted example (deploy, authorize the hardcoded identity, upload a photo, reload → photo persists)
    • The long-term decision: (a) keep on legacy recipe as the programmatic-uploads example, (b) repurpose to a backend-canister storage design, or (c) retire
  2. marc0olo commented on Jul 30, 2026

    @marc0olo
    ContributorAuthor

    Manual testing surfaced a second, independent bug beyond the API mismatch: the app's dfx-era canister-ID discovery (/(.*)\.localhost/ host regex) breaks on icp-cli's name-based frontend URL (http://frontend.local.localhost:8000) — the regex captures frontend.local and Principal.fromText throws Invalid character: "." at module load → white screen.

    Fixed in the working tree alongside the recipe revert: App.jsx now reads the ic_env cookie via safeGetCanisterEnv() (PUBLIC_CANISTER_ID:frontend + IC_ROOT_KEY, agent host = window.location.origin) — the same pattern as hello_world — with ?canisterId= as fallback; the legacy asset-canister recipe serves the cookie, verified via curl. README updated to point at the URL icp deploy prints.

    Verified so far: list returns assets via icp canister call, new bundle serves on both URL forms. Browser upload flow verification in progress.

  3. marc0olo commented on Jul 30, 2026

    @marc0olo
    ContributorAuthor

    ✅ Manual e2e verification passed (2026-07-30): with the recipe revert + cookie-based canister-ID discovery, the app renders the gallery, uploads work after authorize, and photos persist across reloads — on the name-based URL icp deploy prints.

    Remaining in this issue: only the long-term decision (keep on legacy recipe as the programmatic-uploads example / repurpose to backend-canister storage / retire).

  4. marc0olo commented on Aug 4, 2026

    @marc0olo
    ContributorAuthor

    closed via #1464

  5. marc0olo commented on Aug 27, 2026

    @marc0olo
    ContributorAuthor

    Long-term decision: (c) retire. hosting/photo-storage is being deleted from the repo.

    Rationale: we don't want to advertise using the asset canister as programmatic, end-user-facing storage any more. The interim fix in #1464 kept the example alive only by pinning it to the legacy @dfinity/asset-canister recipe, which made it the single example blocking a clean "all frontends are certified-assets" story — and certified-assets has no runtime-upload API to migrate it to (mutations go exclusively through the recipe's sync plugin on icp deploy). Option (b) was rejected as redundant with rust/photo_gallery, which already demonstrates photo storage in a purpose-built backend canister.

    Removed: the example directory, .github/workflows/hosting-photo-storage-example.yml, its CODEOWNERS entry, both hosting/README.md entries (including the "one deliberate exception" note about the legacy recipe), and the photo-storage reference in the AGENTS.md ICP Ninja eligibility rules (genericized — the rule about controller-only setup steps still stands).

    Net effect: no example in the repo uses @dfinity/asset-canister any more.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions