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

@within-7/jetr

v0.11.1

Published

CLI for Jetr static site hosting

Readme

@within-7/jetr

One-command static site hosting on Cloudflare R2 + Workers.

  • Static sites, SPAs, file packs — same command for all three
  • Auto-detected SPA fallback — Vue/React/Svelte routes just work
  • Pretty URLs, _redirects, _headers — Netlify/Pages compatible syntax
  • Atomic deploys + preview URLs — every deploy is reachable forever, rollback is one SQL UPDATE
  • Smart cache tiers — HTML stays fresh, hashed assets get immutable
  • Custom domains, password protection, share tokens — out of the box

Install

npm i -g @within-7/jetr

Or use directly without installing:

npx @within-7/jetr ./dist my-site

Quick Start (zero-config)

# 1. Login (or auto-detected from AITER_TOKEN env)
jetr login

# 2. Build your app, then deploy the output directory
npm run build
jetr ./dist my-blog
# ✔ Deployed!
#   Site:  my-blog
#   URL:   https://my-blog.jetr.within-7.com

That's it. For a Vue/React/Svelte SPA, jetr automatically detects the SPA shape and asks if you want client-side routes to work — answer "yes" and /about, /dashboard/orders, etc. all serve the SPA shell correctly.

What jetr detects

When you run jetr ./dist, the CLI classifies your output as one of:

| Shape | Signal | What jetr does | |---|---|---| | SPA | index.html + ≤ 2 HTML files | Prompts to add SPA fallback so /any/route serves index.html | | Static site | index.html + 3+ HTML files | Deploys as-is; pretty URLs (/about → /about.html) work automatically | | File pack | No root index.html | Serves a clickable directory browser + in-browser viewer for markdown/csv/code |

Override the prompt with flags:

jetr ./dist --ssg     # write _redirects without asking (good for CI)
jetr ./dist --no-ssg  # never modify source, deploy bytes as-is

SSG / SPA configuration

Jetr understands two Netlify/Pages-style config files in your deploy directory. Either drop them in by hand or run:

jetr init --ssg ./dist

…which scaffolds .jetrignore, _redirects, and _headers with commented templates you can edit.

_redirects — routing rules

# SPA fallback (catch-all rewrite)
/*                  /index.html         200

# Legacy URL migration
/old-blog/*         /posts/:splat       301

# API rewrite (serve /backend/x.json as /api/x.json without exposing the path)
/api/*              /backend/:splat     200

# External redirect
/docs               https://docs.example.com    302

Supported: exact paths, * splat, :splat substitution, status 200 (rewrite, URL unchanged) and 30x (HTTP redirect). External 200 rewrites are refused (jetr never proxies third-party content); external 30x pass through.

_headers — per-path HTTP headers

# Global headers (every response)
/*
  X-Frame-Options: DENY
  X-Content-Type-Options: nosniff
  Referrer-Policy: strict-origin-when-cross-origin

# API CORS
/api/*
  Access-Control-Allow-Origin: *
  Access-Control-Allow-Methods: GET, POST

# Long cache for fonts
/fonts/*
  Cache-Control: public, max-age=31536000, immutable

Later rules override earlier ones on the same header key.

Pretty URLs

/about automatically serves /about.html when the latter exists and the requested path has no file extension. Works for nested paths: /blog/post-1 → /blog/post-1.html. This matches the Hugo / Jekyll / Astro convention out of the box — no config needed.

The directory-redirect rule (/docs → /docs/) still fires when a matching .html doesn't exist but a directory does.

Smart caching

Jetr picks Cache-Control based on file type and name:

| File | Header | |---|---| | *.html, *.json, *.xml | max-age=300 (5 min) | | Vite/Webpack/Rollup hashed assets (app.a1b2c3d4.js) | max-age=31536000, immutable | | Other assets (logo.png, styles.css) | max-age=3600 (1 hour) |

Hashed-asset detection requires an asset extension AND an 8+ char basename segment containing at least one digit. Human-named files (my-component-page.js, theme-dark.css) are never tagged immutable by accident.

Atomic deploys + preview URLs + rollback

Every jetr invocation produces a unique deployId. All files for that deploy go to a dedicated R2 prefix; the production URL only serves the latest deploy's bytes once finalize commits an atomic pointer swap. Old deploys remain reachable for preview / rollback.

jetr deploys my-blog
# Active: 7Jb3pK   2026-06-03 14:21   23 files, 1.2 MB
#         qF2nLm   2026-06-03 11:08   23 files, 1.2 MB
#         h8WqEr   2026-06-02 17:55   21 files, 1.0 MB

# Preview a historical deploy
jetr preview my-blog qF2nLm
# https://my-blog--qF2nLm.jetr.within-7.com

# Roll back to it
jetr rollback my-blog qF2nLm
# ✔ Active deploy: qF2nLm

Preview URLs are validated against (siteId, deployId, status='complete') so unrelated deploy IDs can't be probed across sites.

Preview URLs work on the default *.jetr.within-7.com origin only. Custom domains always serve the active deploy. This matches Vercel and Netlify behaviour.

Custom domains

jetr ./dist blog.example.com
# ✔ Deployed!
#   Domain: blog.example.com
#   DNS:    Set blog.example.com CNAME to within-7-jetr.com

The CLI shows the DNS instruction on every deploy (not just the first) so you don't lose it.

Root domains (example.com with no subdomain) are rejected because CNAMEs at the apex are forbidden by DNS — use www.example.com or app.example.com instead.

Password protection + share tokens

# Lock a site
jetr password my-draft hunter2

# Generate a share link that bypasses the password
jetr token create my-draft --note "QA team" --expires 86400
# URL: https://my-draft.jetr.within-7.com/?token=...

# Revoke a token by ID
jetr info my-draft       # lists tokens
jetr token revoke my-draft <token-id>

File-package mode (no index.html)

Drop a folder of mixed files and jetr serves a clickable directory browser with in-browser viewers for:

  • Markdown (rendered HTML)
  • CSV (tabular HTML)
  • Plain text / source code (syntax-highlighted)
  • Images (inline)

Useful for quick file dumps, datasheet shares, asset distribution. Append ?raw to any URL to bypass the viewer and download the underlying bytes.

Command reference

jetr [paths...]                  Deploy directory or files
jetr login                       Authenticate
jetr whoami                      Show current user
jetr logout                      Clear credentials
jetr init [dir] [--ssg]          Scaffold .jetrignore (+ _redirects, _headers)
jetr create <name> [-p PW] [-e SECS]   Create empty site without deploying
jetr list                        List your sites
jetr info <name>                 Show site details (files, tokens, domains)
jetr delete <name> [-y]          Delete a site permanently (prompts unless -y)
jetr password <name> [pw]        Set / remove visitor password
jetr token create <site> [-n NOTE] [-e SECS]   Generate share token
jetr token revoke <site> <id>    Revoke a share token
jetr deploys <site>              List deploy history
jetr rollback <site> <deployId> [-y]   Flip active pointer to a past deploy (prompts unless -y)
jetr preview <site> <deployId>   Print preview URL

Deploy flags

--ssg                            Force-write _redirects for SPA-shaped sites
--no-ssg                         Skip SSG detection
--concurrency <n>                Max parallel uploads (default: JETR_CONCURRENCY env or 10)

Exit codes

Scripts and CI can check $? to branch on the failure reason:

| Code | Meaning | Typical trigger | |---|---|---| | 0 | Success | — | | 1 | Generic error | Unexpected failure | | 2 | Usage / argument error | Root domain, missing required arg | | 3 | Auth error | Not logged in, token expired (jetr login) | | 4 | Network error | Cannot reach API (check internet connection) | | 5 | Not found / forbidden | Site 404, deploy doesn't exist, site belongs to another user | | 6 | Conflict | Deploy invalid / superseded, file not in upload set, domain already in use |

Example:

jetr ./dist my-site
case $? in
  0) echo "deployed" ;;
  3) echo "need to run jetr login" ;;
  4) echo "network issue — retry?" ;;
  6) echo "conflict — may need to retry deploy" ;;
  *) echo "deploy failed" ;;
esac

Environment variables

| Variable | Effect | |---|---| | AITER_TOKEN | Auth token (preferred over JETR_TOKEN and ~/.jetr/config.json) | | JETR_TOKEN | Fallback auth token | | JETR_CONCURRENCY | Default upload concurrency (overridden by --concurrency flag, default 10) | | JETR_MAX_RETRIES | Max HTTP retry attempts for transient errors (default 3) |

Files jetr writes / reads in your deploy dir

| File | Purpose | |---|---| | .jetrignore | Patterns to skip during upload (created by jetr init) | | .jetrkeep | Force-include files that would otherwise be ignored | | .jetrrc | Site-name memory (created on first deploy) | | .jetr/hash-cache.json | SHA-256 hash cache keyed by path+size+mtime — speeds up unchanged-file detection across deploys | | _redirects | Routing rules — compiled to .jetr/meta.json on the server, raw file NOT uploaded | | _headers | Per-path HTTP headers — also compiled to .jetr/meta.json, raw file NOT uploaded |

License

MIT