New:Introducing Socket Scanning for VS Code Marketplace Extensions.Learn more →
Get Started

@ultimat3/pwa

Package Overview
Dependencies
Maintainers
1
Versions
106
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@ultimat3/pwa

Generated service worker, web manifest, icons, push and version-skew handling.

Source
npmnpm
Version
8.0.0
Version published
Maintainers
1
Created
Source

📲 @ultimat3/pwa

You never open sw.js. It is emitted from the route table. That is this package's whole thesis: a hand-written service worker encodes routing decisions a second time, and the second copy is the one nobody updates.

const { source, precache, warnings } = generateServiceWorker(describeRoutes(), config, buildId);

Render mode → runtime strategy

Render modeStrategyWhy
staticcache-firstbuilt once; the URL's bytes only change on deploy
isrstale-while-revalidatestale is correct by construction, refresh behind
streamstale-while-revalidateshell is reusable, holes come from the network
ssrnetwork-firstfreshness is the point; cache is the offline safety net
spacache-firstthe shell is identical for every actor

Overrides: offline: 'network-only' forces network-only; a per-route strategy wins over everything. api/ routes get no cache rule at all.

offlineMeaning
precachefetched at install, keyed by content hash
runtimecached on first visit under the render-mode strategy
network-onlynever served from a cache

Version skew — the thing that actually breaks PWAs

A client loaded build A hours ago. Build B deletes A's chunks. The next lazy import 404s and the app dies with a blank screen and no error anyone can act on.

MechanismRule
Build idimmutable per deploy, derived from the commit sha; X_BUILD_ID_MISSING if absent
Client → serverevery SW-proxied request carries x-ultimate-build
RetentionretentionPlan(deploys, keep) keeps the last N deploys' assets alive (default 3)
Stale clientgets AppUpdateAvailable, never a 404
Forced reloadonly for forceOn reasons, only after graceMs (default 6h)
Preview deployscache names are x-<kind>-<buildId>, so a branch build cannot poison production
detectSkew(clientBuildId, serverBuildId);   // 'current' | 'stale' | 'unknown'
updateSignal({ clientBuildId, serverBuildId, policy: updatePolicy() });
// → { type: 'AppUpdateAvailable', from, to, forced, deadlineAt }

unknown means no id was sent — a first load or a crawler — and is never treated as stale.

The offline fallback is mandatory in the type

X_PWA_NO_OFFLINE_FALLBACK: no offline fallback route
  cause: app.config.ts has no `offline` block, so an offline navigation would show the browser's error page
  fix:   create app/offline.tsx and set offline.fallback

requireOfflineFallback(config) runs inside generateServiceWorker, so the build fails before an un-shippable PWA exists.

Capabilities are opt-in, and gate bytes

CapabilityManifest memberSW code
push—push + notificationclick listeners
backgroundSync—sync listener + outbox flush
badging—navigator.setAppBadge after a push
shareTargetshare_target—
fileHandlersfile_handlers—
protocolHandlersprotocol_handlers—

A disabled capability emits neither the manifest member nor the SW code. An unused capability ships zero bytes and asks for zero permissions.

Three of the six are manifest-only, and the — in their SW column is load-bearing: the OS hands a share, a file or a protocol URL to a route the app already serves, so there is no worker branch to gate. CAPABILITY_SW_MARKERS is checked against the emitted sw.js in both directions, so a claim here that the generator does not honour is a failing test rather than an installed app announcing a capability nothing implements.

Public API

ExportOwns
generateServiceWorkersw.js from the route table; deterministic for identical input
strategyFor, MODE_STRATEGY, cacheFirst, …the four strategies + the mapping table
buildPrecacheManifestprecache entries (url + content-hash revision), size warnings
buildId, detectSkew, retentionPlan, updatePolicy, updateSignalversion skew
generateWebManifestthe manifest + theme-color metas for both schemes
planIcons, requireSourceIcon, maskableSafeZoneicons and splashes from one source
BuiltinImagePipelinerenders that plan: one square PNG per entry, deterministic
requireOfflineFallbackthe mandatory offline route
backgroundSyncSource, retryDelayMsthe Background Sync trigger
renderPushPayload, pushSource, subscribeSourceWeb Push, per-locale bodies
createInstallController, iosInstallGuidanceinstall prompt, never on first paint
PwaStrategyExhaustedError and the other errors.ts classesthe codes this package throws, catchable by an app

Notes

  • Theme colours come from the design tokens for both schemes. The manifest spec carries one theme_color, so the dark value is emitted as a media-scoped <meta name="theme-color"> — otherwise an installed dark app launches with a light status bar every time.
  • Precache revisions are content hashes, never the build id. Keying on the build id re-downloads every asset on every deploy.
  • The mutation queue lives in @ultimat3/realtime, not here (SRP). This package owns only the Background Sync trigger that asks realtime to flush.
  • Push bodies are rendered server-side per subscriber locale, from the locale stored on the subscription. A notification in the wrong language is a real bug, and the sending server has no request context to infer one from.
  • Icons come from one source image. X_PWA_ICON_MISSING names the file to add; BuiltinImagePipeline renders the whole matrix from it through @ultimat3/core's image pipeline — no sharp, no vendor image CDN, no native build step. Every output is a square PNG, because type: 'image/png' is what the manifest declares. A maskable icon's artwork lands exactly inside maskableSafeZone(size); the ring around it is background, which is hex or transparent (there are no named colours). Same bytes in, same bytes out.
  • Every HTML sink goes through one escaper. appleTouchLinks and renderThemeColorMeta interpolate app configuration into attributes, so both run it through escapeAttribute from @ultimat3/seo (tier 1, and the one this package can reach — @ultimat3/render's html.ts is tier 4, sideways). Never a second escaper here.
  • A precache URL may already carry a query. PrecacheAsset.url is public API and bundlers emit ?v=<hash> of their own, so the install block picks ? or & per entry. A fixed ? produced ...?locale=en?v=<rev>, and because cache.addAll is all-or-nothing a single non-200 there means the worker never installs at all.
  • Route data arrives as data. @ultimat3/render and @ultimat3/pwa are both tier 4, so PwaRoute is a structural view of RouteDescriptor, never an import.

FAQs

Package last updated on 23 Aug 2026

Related posts