Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .changeset/viewer-alpha.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
"@transloadit/viewer": patch
---

Publish the first alpha of `@transloadit/viewer`: native responsive images from Transloadit Storage
or an origin-pinned HTTP/S3 Smart CDN Template, with a Next.js Server Component and a resolved-model
renderer. Image bytes go directly from Smart CDN to the browser.

This is an early, images-only API that may change between releases. Install the `alpha` tag and pin
the exact version. Storage and browser CLI login require the matching backend and Console rollout;
an existing compatible HTTP/S3 Template does not require a Storage migration.
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ jobs:
- uses: changesets/action@a45c4d594aa4e2c509dc14a9f2b3b67ba3780d0d
with:
version: corepack yarn changeset:version:release
publish: corepack yarn changeset publish
publish: corepack yarn release:publish
commitMode: github-api
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Expand Down
12 changes: 10 additions & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,12 +116,20 @@ Changelog guidance:

Manual fallback (maintainers only):

- `corepack yarn changeset publish`
- On the generated version PR's merged commit: `corepack yarn release:publish`.
- This publishes Viewer with its explicit `alpha` tag, then uses `changeset publish` for the
remaining packages and `changeset tag` for release discovery. A failed registry lookup stops the
release; retries do not republish an existing version.

Notes:

- CI publishing requires npm trusted publishing (OIDC) configured for this repo.
- Scoped packages now publish to the default `latest` dist-tag unless a workflow explicitly overrides it.
- Scoped packages publish to `latest`, except `@transloadit/viewer`, which is an alpha and uses
`alpha`. Its `publishConfig.tag` alone is insufficient because Changesets passes `--tag latest`.
- Mark the Viewer GitHub release as a prerelease and verify the npm tags after publishing. On first
publication, npm may also assign `latest`; remove that Viewer tag if present.
- Viewer prepack uses incremental TypeScript builds, like Utils. Do not recursively clean project
references there: Changesets can pack dependent packages concurrently.
- If this was a pre-release, remember to reset the [npm `latest` tag](https://www.npmjs.com/package/transloadit?activeTab=versions) to the previous version (replace `x.y.z` with previous version):
- `npm dist-tag add transloadit@X.Y.Z latest`

Expand Down
18 changes: 9 additions & 9 deletions docs/img-dogfood.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,15 @@
These are maintainer-only packing, SDK seed and devdock notes, not consumer prerequisites.
Use the [package README](../packages/img/README.md) for the application integration.

## September 17 consumer release gates
## Consumer release gates

Publish the minor Node/legacy release only after API2 #9057 and Content #5973 are deployed.
Device login, public delivery and safe CLI-key revocation need that coordinated rollout.
Kevin authorized the first Viewer alpha and the normal SDK release train on September 21.
Package publication does not deploy API2 or enable Storage. Device login, public Storage delivery
and safe CLI-key revocation still need the coordinated API2 #9057 and Console rollout.
Apply the CLI approval-key-identity migration before deploying API2; logout now signs explicit
`action: 'revoke_auth_key'` intent. Native move responses and `builtin/storage-serve@0.0.3` must
be available before publishing the new consumer helpers. Viewer remains private dogfood.
At publication, replace preview-branch documentation links with their merged main locations.
be available before using those consumer helpers. Existing compatible HTTP/S3 image Templates
can use Viewer without migrating to Storage. The first Viewer release is an images-only alpha.
Production Bunny checks, independent backup/restore and app-owned access checks remain gates;
passing the local private-media fixture is not a production deployment claim.

Expand All @@ -27,8 +28,8 @@ Storage uses relative catalog paths; custom HTTP/S3 Templates accept relative in
intrinsic dimensions. Their fixed origins and import credentials belong in the Template, not JSX.
See the package reference's custom Template recipe; the historical canaries below cover Storage.

This workspace remains private at version `0.0.0` while the API and production dogfood soak. Do not
depend on it from npm yet.
Use the package README's `alpha` install for released consumers. The local tarball procedure below
is for verifying unreleased changes and does not establish registry or production availability.

## Seed your first image

Expand All @@ -51,8 +52,7 @@ Keep the app's stock Next.js TypeScript configuration and Node/React type depend
### Install the local packages

Use a clean checkout of [transloadit/node-sdk](https://github.com/transloadit/node-sdk), at the
reviewed revision of [PR #500](https://github.com/transloadit/node-sdk/pull/500). For example,
`gh pr checkout 500` selects that PR; record `git rev-parse HEAD` before packing. From that SDK
reviewed revision being tested; record `git rev-parse HEAD` before packing. From that SDK
checkout, install its locked dependencies and pack into your own temporary directory:

```bash
Expand Down
85 changes: 85 additions & 0 deletions docs/prompts/2026-09-21-viewer-alpha-release.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
# Viewer alpha: Changesets release and Content adoption

## Requested outcome

Kevin authorized publishing the first Viewer alpha and completing the existing Version Packages
PR #502, including its Node/CLI, Utils, Types, Zod and MCP releases. Use the release procedure in
`CONTRIBUTING.md`: changeset in a reviewed PR, generated version/changelog PR, then trusted
publishing. Do not hand-edit versions or generated changelogs, deploy API2, or merge Uppy.

The first Viewer patch changeset should produce **0.0.1**. This is an alpha product, not a stable
API promise: label its description and README accordingly, provide the `alpha` npm tag, and mark
its GitHub release as a prerelease. Record the actual registry version and tags before declaring
it available. The existing Changesets publisher passes `--tag latest`, overriding a package's
`publishConfig.tag`; that field alone is not proof of the final registry state. Do not put the
whole SDK into Changesets prerelease mode merely to release one experimental package.

Viewer needs Utils 4.9's new exports. Let the existing Utils changesets and normal dependency
versioning update its registry dependency, and verify that the generated Viewer manifest requires
at least 4.9.0 before publishing. The old private workspace protocol must not escape into npm.

## Gates

- [x] Read contributing/release instructions and confirm the existing release PR's scope.
- [x] Reproduce private-package/registry-dependency metadata failure with a regression test.
- [x] Verify package checks and the packed Next browser fixture (Chromium/WebKit, both cache modes,
and development diagnostics). Run the versioned release dry run in PR CI.
- [ ] Reconcile council review; open and finish the alpha preparation PR.
- [ ] Inspect generated #502 versions, dependency floors, changelogs and exact-head CI.
- [ ] Merge #502, watch trusted publication and verify every expected registry version.
- [ ] Verify Viewer alpha tag and GitHub prerelease; prevent an accidental stable `latest` claim.
- [ ] Prove a registry-installed consumer, not just a workspace-linked or vendored package.

For a new npm package, trusted-publisher bootstrap may need a maintainer action. Follow the
documented `release:publish` Changesets fallback only if the actual CI failure requires it, on the exact
generated release commit, after identifying which packages remain unpublished. Never republish a
version, expose credentials or treat a successful pack as a successful release.

## Review and verification

There were no comments or reviews on #502 at inspection. The first council found two valid release
issues, both reproduced red-first and fixed: Changesets overriding the alpha npm tag, and Viewer's
recursive TypeScript clean deleting dependent Utils artifacts during concurrent packaging.
The publisher now explicitly publishes only Viewer to alpha, then lets Changesets publish the
remaining packages and generate tags. Registry lookup failures fail closed and published versions
are skipped on retry. Viewer uses the same incremental build approach as Utils. A follow-up council
reported no further findings. An explicit TypeScript check caught an overloaded `execa` type
extraction error; the options now use its public `Options` type. Claude's review legs could not run because their monthly
spend limit was reached; do not count that leg as a successful independent review.

Local `verify:full`, `check`, the 30 image fixture contract tests and the seven publisher tests pass.
The packed fixture passed both production modes (58 browser cases each), the secretless public-only
builds, and ten development cases. Evidence: `/tmp/viewer-alpha-20260921.gU9s3H/`.

## Before API2 is deployed

Storage Built-ins, native catalog APIs and device login need the matching backend rollout. The
README must not imply that merging or publishing the SDK has deployed those endpoints. Existing
origin-pinned HTTP/S3 Templates are independently usable.

Content already has a signed website-image Template and a static candidate policy. Its regular
Viewer `Image` direct-delivery factory intentionally calls `connection()` and rotates short-lived
signatures. Replacing the current static site wrapper with that factory would change prerendering
and cache behavior. Start with the published package and its resolved-model `TransloaditPicture`
renderer, preserving the existing URLs, origin limits, expiry, layout, responsive widths, no-script
fallback and WebKit hydration safeguards. Media-gated slots need their existing inert fallback
until the shared renderer supports the same contract. Do not silently make pages dynamic or add
per-image redirect requests for this public-site adoption.

The later production sequence remains backend deploy by Kevin/deployer → Console browser and
`gog` account/workspace proof → published CLI → Storage dogfood in Content and the Convex wedding
golden path. Keep application authorization/metadata in Convex and do not merge Uppy.

## Build monitoring

Monitoring began September 21, 2026 at 18:15 UTC, with a three-hour deadline (21:15 UTC), using
Content's `_scripts/alphalib/bin/gh-run-watch.ts`. SDK main `a2c5dd7` is green. API2 main `f664f5e`
was superseded/cancelled by `3abb5f0b81`; follow run `35637074003`, which includes the Storage merge.
Its predecessor `35627027644` still occupied the main concurrency group at inspection.
At 18:43 UTC, another main merge superseded that pending run: follow `35640243219` at `3555e451c2`
without extending the original 21:15 UTC monitoring deadline.

Content main run `35636664743` failed before checkout on Spot-interrupted runners, including
`sb93ep` with deadline 18:13:19 UTC. Preserve the logs and do not call that run green. Evidence and
watcher logs: `/tmp/viewer-alpha-20260921.gU9s3H/`. Report the actual final API2 buildtar URL when
verified; deployment belongs to Kevin and the deployer agent.
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"verify:full": "yarn verify && yarn knip && yarn test:types",
"changeset:version:release": "yarn changeset version && YARN_ENABLE_IMMUTABLE_INSTALLS=false yarn install",
"release:pack:dry-run": "node scripts/release-dry-run.ts",
"release:publish": "node scripts/publish-release.ts",
"lint:js": "biome check .",
"lint:ts": "yarn tsc:types && yarn tsc:node && yarn tsc:zod && yarn tsc:img && yarn workspace @transloadit/notify-url-relay lint:ts",
"lint:transloadit-sync": "node scripts/check-transloadit-sync.ts",
Expand All @@ -27,7 +28,7 @@
"pack": "node scripts/pack-transloadit.ts",
"parity:transloadit": "node scripts/prepare-transloadit.ts && node scripts/fingerprint-pack.ts packages/transloadit --ignore-scripts --quiet --out /tmp/transloadit-after.json && node scripts/verify-fingerprint.ts --current /tmp/transloadit-after.json --diff",
"test:img:fixture": "node scripts/test-img-next-fixture.ts",
"test:unit": "vitest run ./scripts/withProcess.test.ts ./scripts/img-next-fixture.test.ts ./scripts/knip.test.ts && yarn workspace @transloadit/utils test:unit && yarn workspace @transloadit/viewer test:unit && yarn workspace @transloadit/node test:unit && yarn workspace @transloadit/mcp-server test:unit && yarn workspace @transloadit/types test:unit && yarn workspace @transloadit/zod test:unit && yarn workspace @transloadit/notify-url-relay test:unit",
"test:unit": "vitest run ./scripts/withProcess.test.ts ./scripts/img-next-fixture.test.ts ./scripts/knip.test.ts ./scripts/publish-release.test.ts && yarn workspace @transloadit/utils test:unit && yarn workspace @transloadit/viewer test:unit && yarn workspace @transloadit/node test:unit && yarn workspace @transloadit/mcp-server test:unit && yarn workspace @transloadit/types test:unit && yarn workspace @transloadit/zod test:unit && yarn workspace @transloadit/notify-url-relay test:unit",
"test:types": "yarn workspace @transloadit/zod test:types",
"test:e2e": "yarn workspace @transloadit/node test:e2e",
"test": "yarn workspace @transloadit/node test",
Expand Down
18 changes: 9 additions & 9 deletions packages/img/README.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
# `@transloadit/viewer`

Responsive images from Transloadit Storage or your existing HTTP/S3 assets, for Next.js.
Native `picture/srcset`; bytes go straight from
Smart CDN (`<workspace>.tlcdn.com`) to the browser, never through Next's image optimizer.
**Alpha — API may change between releases. Pin the exact version in production. Images only for now.**

Responsive images from Storage or existing HTTP/S3 assets, for Next.js. Native `picture/srcset`;
bytes go straight from Smart CDN (`<workspace>.tlcdn.com`) to the browser, never through Next's optimizer.

## Quickstart

Next.js 16.3.3+ App Router, React 19, Node.js runtime.
**Unpublished dogfood:** ask a maintainer for matching viewer/utils/node/types tarballs.
After release: `npm install @transloadit/viewer && npm install --save-dev @transloadit/node`.
pnpm: `pnpm add @transloadit/viewer && pnpm add -D @transloadit/node`;
Yarn: `yarn add @transloadit/viewer && yarn add -D @transloadit/node`.
`npm install @transloadit/viewer@alpha && npm install --save-dev @transloadit/node`.
pnpm: `pnpm add @transloadit/viewer@alpha && pnpm add -D @transloadit/node`;
Yarn: `yarn add @transloadit/viewer@alpha && yarn add -D @transloadit/node`.
Storage needs a matching API2 deployment; [existing HTTP/S3 assets](#existing-http-or-s3-assets) do not.

Run beside `package.json`. Start with `auth login` even without an account: choose Sign up in the
browser it opens, create a free workspace, and approve the CLI. For `./hero.jpg`, use any JPEG you have.
Expand Down Expand Up @@ -105,5 +106,4 @@ Lost metadata? Restore the committed catalog or [recover it from Storage](./docs
## Reference

[Store an image from your application server](https://github.com/transloadit/node-sdk/blob/main/packages/node/README.md#store-an-image).

[Full reference](./docs/reference.md) · [Version-pinned delivery](./docs/reference.md#cache-and-markup-cost) · [Maintainer dogfood setup](https://github.com/transloadit/node-sdk/blob/img-onboard/docs/img-dogfood.md).
[Full reference](./docs/reference.md) · [Version-pinned delivery](./docs/reference.md#cache-and-markup-cost) · [Maintainer dogfood setup](https://github.com/transloadit/node-sdk/blob/main/docs/img-dogfood.md).
11 changes: 7 additions & 4 deletions packages/img/package.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
{
"name": "@transloadit/viewer",
"version": "0.0.0",
"description": "Native responsive images from Transloadit Storage and Smart CDN Templates",
"private": true,
"description": "Alpha: native responsive images from Transloadit Storage and Smart CDN Templates",
"type": "module",
"license": "MIT",
"publishConfig": {
"access": "public",
"tag": "alpha"
},
"repository": {
"type": "git",
"url": "https://github.com/transloadit/node-sdk",
Expand Down Expand Up @@ -54,15 +57,15 @@
"./package.json": "./package.json"
},
"scripts": {
"build": "../../node_modules/.bin/tsc --build --clean tsconfig.build.json && ../../node_modules/.bin/tsc --build tsconfig.build.json",
"build": "../../node_modules/.bin/tsc --build tsconfig.build.json",
"check": "yarn lint:ts && yarn test:unit",
"lint:ts": "../../node_modules/.bin/tsc --build tsconfig.build.json && ../../node_modules/.bin/tsc --noEmit --project tsconfig.json",
"prepack": "yarn build",
"test:unit": "yarn build && ../../node_modules/.bin/vitest run ./test"
},
"dependencies": {
"@noble/ciphers": "^1.3.0",
"@transloadit/utils": "workspace:^",
"@transloadit/utils": "^4.8.1",
"server-only": "^0.0.1",
"thumbhash": "0.1.1"
},
Expand Down
8 changes: 4 additions & 4 deletions scripts/fixtures/img-next/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions scripts/fixtures/img-next/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
},
"dependencies": {
"@noble/ciphers": "1.3.0",
"@transloadit/utils": "4.8.1",
"next": "16.3.4",
"react": "19.2.8",
"react-dom": "19.2.8",
Expand Down
Loading
Loading