npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@tempmd/client

v0.2.0

Published

Runtime-neutral client for publishing temporary previews to temp.md

Downloads

522

Readme

@tempmd/client

Runtime-neutral preview publishing for browsers, Electron renderers, Workers, and Node.js 20+. It uses web-standard Fetch, Web Crypto, Blob, and typed arrays without importing Node built-ins.

Install

npm install @tempmd/client

Publish a preview

Anonymous publishing works without an account or API key:

import { TempmdPreviewClient } from "@tempmd/client";

const previews = new TempmdPreviewClient();

const result = await previews.publishPreview({
  files: [
    {
      path: "index.html",
      data: "<!doctype html><h1>Preview</h1>",
      contentType: "text/html; charset=utf-8",
    },
  ],
  spaMode: true,
  onProgress: (progress) => console.log(progress),
  onState: saveToProtectedStorage,
});

console.log(result.record.canonicalUrl);

onState receives portable resumable state before uploads begin and again after finalization. Store it in the host application's protected storage. The state may contain update and short-lived upload capabilities.

Publish with a delegated grant

Products using @tempmd/platform can mint a short-lived publish grant on their server. Pass the grant to the low-level client as its account token; never pass the Application key to a browser or renderer.

import { TempmdClient, TempmdPreviewClient } from "@tempmd/client";

const api = new TempmdClient({
  accountToken: publishGrant,
  clientIdentity: "my-builder/1.0.0",
});
const previews = new TempmdPreviewClient(api);

const result = await previews.publishPreview({
  files: [{ path: "index.html", data: html }],
  onState: saveToProtectedStorage,
});

A publish grant is single-purpose, short-lived, and constrained by the limits chosen by the issuing Application.

A delegated publish returns record.ownershipState === "platform" and no updateToken or claim link. A successful publish still clears pending state and emits the ready progress event. Keep the record to identify the preview; it does not grant permission to update it.

For the next update, mint a new operation: "update" grant on your server with previewId: result.record.tempId. Construct a new client with that grant, then call updatePreview(result.record, { files: nextFiles }). Interrupted uploads can still use resumePreview(savedState, { files }) with the saved upload capability. Read status and revoke platform previews through your server using @tempmd/platform; the browser client's status and revoke methods require a scoped update token.

Update the same URL

Pass the last finalized record to updatePreview(). Unchanged files are skipped and the canonical URL remains stable.

const next = await previews.updatePreview(result.record, {
  files: nextFiles,
  onState: saveToProtectedStorage,
});

console.log(next.record.canonicalUrl === result.record.canonicalUrl); // true

Resume an interrupted publish

Persist every value delivered to onState. If a session is interrupted, pass the last state back to resumePreview() with the same files and settings:

const resumed = await previews.resumePreview(savedState, {
  files,
  spaMode: true,
  onState: saveToProtectedStorage,
});

The client validates that the saved session and local bundle still match before continuing.

Status and revoke

const status = await previews.getPreviewStatus(result.record);

await previews.revokePreview(result.record);

Errors and cancellation

Use an AbortSignal to cancel a workflow. Validation failures throw BundleValidationError; HTTP failures from the low-level client throw ApiError with status, code, optional requestId, and optional retryAfter fields.

import { ApiError, BundleValidationError } from "@tempmd/client";

try {
  await previews.publishPreview({ files, signal: controller.signal });
} catch (error) {
  if (error instanceof BundleValidationError) console.error(error.issues);
  if (error instanceof ApiError) console.error(error.status, error.code);
}

Security requirements

  • Treat the entire PreviewIntegrationState and PreviewRecord as secrets.
  • Never put update tokens, upload tokens, or grants in URLs, logs, analytics, or rendered content.
  • Do not send cookies or enable credentialed CORS requests.
  • Tell users which files will be uploaded, that previews are public by default, and when they expire.
  • Persist pending state before uploads begin so interrupted sessions can resume.

Persisted state follows preview-state-v1.json.

Main exports

  • TempmdPreviewClient — high-level publish, update, resume, status, and revoke workflow.
  • TempmdClient — low-level publish-session HTTP client.
  • validateBundle and manifestHash — bundle validation and hashing helpers.
  • ApiError and BundleValidationError — structured failures.
  • Public TypeScript types for files, sessions, progress, records, and state.

See the integration guide and preview infrastructure overview.