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

@upend/cli

v0.1.5

Published

Anti-SaaS stack. Deploy live apps with Claude, Postgres, and rsync.

Readme

upend

Anti-SaaS stack. Your code, your server, your database. Deploy via rsync. Edit live with Claude.

Bun + Hono + Neon Postgres + Caddy. Custom JWT auth. Claude editing sessions with git worktree isolation. Hot-deployed frontend apps.

Prerequisites

  • Buncurl -fsSL https://bun.sh/install | bash
  • Caddybrew install caddy
  • Claude Codenpm i -g @anthropic-ai/claude-code
  • A Neon account (free tier works)
  • Optionally: neonctlnpm i -g neonctl (automates DB setup)

Quickstart

# create a new project
bunx @upend/cli init my-project

# follow the prompts — if neonctl is installed, it will:
#   1. create a Neon database
#   2. enable the Data API (PostgREST)
#   3. configure JWKS for JWT auth
#   4. generate RSA signing keys
#   5. encrypt your .env with dotenvx

cd my-project

# add your Anthropic API key
# (edit .env, then re-encrypt)
vi .env
bunx @dotenvx/dotenvx encrypt

# run migrations
bunx upend migrate

# start dev
bunx upend dev

Open http://localhost:4000 — you'll see the dashboard.

What you get

my-project/
├── apps/                 → hot-deployed frontends (drop files in, they're live)
├── migrations/
│   └── 001_init.sql      → starter migration
├── services/             → custom Hono services (optional)
├── upend.config.ts       → project config
├── CLAUDE.md             → instructions for Claude editing sessions
├── .env                  → encrypted credentials (safe to commit)
├── .env.keys             → decryption keys (gitignored)
├── .keys/                → JWT signing keys (gitignored)
└── package.json

URLs

Everything runs through Caddy at :4000:

| URL | What | |-----|------| | http://localhost:4000 | Dashboard — chat with Claude, browse data, manage apps | | /api/auth/signup | Create account — POST {email, password}{user, token} | | /api/auth/login | Login — POST {email, password}{user, token} | | /.well-known/jwks.json | Public keys for JWT verification | | /apps/<name>/ | Your apps, served from the filesystem |

Auth

Sign up:

curl -X POST http://localhost:4000/api/auth/signup \
  -H 'Content-Type: application/json' \
  -d '{"email":"[email protected]","password":"yourpassword"}'
# → { user: { id, email }, token: "eyJ..." }

Use the token everywhere:

TOKEN="eyJ..."
curl http://localhost:4000/api/data/example \
  -H "Authorization: Bearer $TOKEN"

Data API

Your tables are automatically available as REST endpoints via Neon's Data API:

# list rows
curl /api/data/example?order=created_at.desc \
  -H "Authorization: Bearer $TOKEN"

# create
curl -X POST /api/data/example \
  -H "Authorization: Bearer $TOKEN" \
  -H 'Content-Type: application/json' \
  -H 'Prefer: return=representation' \
  -d '{"name":"hello","data":{"key":"value"}}'

# update
curl -X PATCH '/api/data/example?id=eq.5' \
  -H "Authorization: Bearer $TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"name":"updated"}'

# delete
curl -X DELETE '/api/data/example?id=eq.5' \
  -H "Authorization: Bearer $TOKEN"

PostgREST filter operators: eq, neq, gt, gte, lt, lte, like, ilike, is, in, not.

Migrations

Plain SQL files in migrations/, numbered sequentially:

# create a migration
cat > migrations/002_projects.sql << 'SQL'
CREATE TABLE projects (
  id BIGSERIAL PRIMARY KEY,
  name TEXT NOT NULL,
  owner_id UUID REFERENCES users(id),
  created_at TIMESTAMPTZ DEFAULT now()
);
SQL

# run it
bunx upend migrate

Or tell Claude in the dashboard: "add a projects table with name and owner" — it'll create the migration and run it.

Apps

Apps are static files in apps/<name>/. No build step. Drop files in, they're instantly live at /apps/<name>/.

From the dashboard, tell Claude: "build a todo app" — it creates the files in a git worktree, you preview them, then publish to live.

Apps can call the API at the same origin:

const token = localStorage.getItem('upend_token');
const res = await fetch('/api/data/projects?order=created_at.desc', {
  headers: { 'Authorization': `Bearer ${token}` }
});
const projects = await res.json();

Editing with Claude

The dashboard at / has a built-in chat. Each conversation creates an isolated git worktree — Claude edits files there, you preview the changes, then click Publish to merge into live.

If something breaks, close the session without publishing. Your live code is untouched.

Deploy

Provision infrastructure

# provision an EC2 instance (t4g.small, Amazon Linux 2023)
bunx upend infra:aws

# this creates:
#   - EC2 instance with Bun, Node, Caddy, Claude Code
#   - security group (ports 22, 80, 443)
#   - SSH key pair
#   - SSH config entry: "ssh upend"

Deploy your code

# set your deploy target in .env
DEPLOY_HOST=ec2-user@<ip>

# deploy (rsync → install → migrate → restart)
bunx upend deploy

Register JWKS (after first deploy)

Neon needs to reach your JWKS URL to validate JWTs for the Data API. After your first deploy, when your domain is live:

bunx upend setup:jwks

Operations

# check service health, disk, memory, cron jobs
bunx upend status

# tail logs (all services, or pick one)
bunx upend logs
bunx upend logs api
bunx upend logs claude
bunx upend logs -f              # follow in realtime

# SSH into the remote instance
bunx upend ssh                  # interactive shell, cd'd to project
bunx upend ssh "bun -v"         # run a command

Workflows

Workflows are TypeScript files in workflows/ that run on a cron schedule or manually:

# list workflows and their schedules
bunx upend workflows

# run one manually
bunx upend workflows run cleanup-sessions

# install cron schedules (also happens on deploy)
bunx upend workflows install

Workflows are also visible in the dashboard with a manual trigger button.

CLI Commands

| Command | What | |---------|------| | upend init <name> | Scaffold a new project (creates Neon DB, generates keys, encrypts env) | | upend dev | Start gateway + claude + caddy locally | | upend migrate | Run SQL migrations from migrations/ | | upend deploy | rsync to remote, install, migrate, restart | | upend status | Check remote service health | | upend logs [service] | Tail remote logs (-f to follow) | | upend ssh [cmd] | SSH into remote instance | | upend workflows | List, run, or install workflow cron schedules | | upend env:set <K> <V> | Set an env var (decrypts, sets, re-encrypts) | | upend infra:aws | Provision an EC2 instance |

Config

upend.config.ts:

import { defineConfig } from "@upend/cli";

export default defineConfig({
  name: "my-project",
  database: process.env.DATABASE_URL,
  dataApi: process.env.NEON_DATA_API,
  deploy: {
    host: process.env.DEPLOY_HOST,
    dir: "/opt/upend",
  },
});

Philosophy

  • One server per customer. Vertical scaling. No multi-tenant complexity.
  • No git workflows. Claude edits live (in a worktree). Publish when ready.
  • No CI/CD. rsync --delete is the deploy.
  • No build step. Bun runs TypeScript directly. Apps are static files.
  • Encrypted env. .env is encrypted with dotenvx — safe to commit. .env.keys is gitignored.
  • Snapshots, not rollback strategies. Before any change, snapshot files + database. Undo = restore.