This guide helps you set up nums with Upstash Redis, run it locally, deploy to Vercel, and verify everything works end‑to‑end.
1

Fork and clone

git clone https://github.com/advayc/nums.git
cd nums
You can also import the repo directly into Vercel and skip local cloning.
2

Create Redis (Upstash recommended)

If you provide both UPSTASH_REDIS_URL and UPSTASH_REDIS_PASSWORD, nums will build a proper REDIS_URL automatically.
3

Configure environment variables

Create a .env file in the repo root:
# Required for /hit authorization (send via X-Auth-Token or ?token=)
SECRET_TOKEN=YOUR_RANDOM_SECRET

# Redis via Upstash (recommended)
UPSTASH_REDIS_URL=your-upstash-host:port
UPSTASH_REDIS_PASSWORD=your-password

# Alternatively provide a full redis URL
# REDIS_URL=rediss://default:password@host:port

# Optional (local server only)
PORT=8080
REDIS_PREFIX=hits:
FAIL_FAST_REDIS=0
Only /hit requires a secret. Read endpoints (/count, /count.txt, /badge, /badge.json) are public.
4

Run locally

go run ./cmd/server
Verify endpoints:
# increment (requires your secret)
curl -H "X-Auth-Token: $SECRET_TOKEN" "http://localhost:8080/hit?id=home"

# read JSON and text
curl "http://localhost:8080/count?id=home"
curl "http://localhost:8080/count.txt?id=home"
You should see a JSON response like {“id”:“home”,“hits”:1} from /hit and a number from /count.txt.
5

Deploy to Vercel

  1. Push your fork to GitHub.
  2. Import the repo in Vercel: https://vercel.com/new
  3. Add the same env vars in Project → Settings → Environment Variables.
  4. Deploy. Your URL will look like https://<project>.vercel.app (or your custom domain).
Never expose your secret token in client-side code. For client websites, route increment requests through a server function.
6

Add a badge to your README

  • Shields (recommended):
![hits](https://img.shields.io/endpoint?url=https%3A%2F%2F<project>.vercel.app%2Fbadge.json%3Fid%3Dhome%26label%3Dhits%26cacheSeconds%3D30)
  • Direct SVG (terminal style):
![hits](https://<project>.vercel.app/badge?id=home&style=terminal&label=hits)
cacheSeconds in /badge.json is clamped to 30–3600 seconds.