TinyNum is a Next.js app that lets users store public text or URLs and retrieve them later using a small integer key.
- Data is public.
- Data expires after 10 minutes.
- Expired keys are reused (smallest available key first).
- Create entry API: stores text/URL and returns an integer key.
- Retrieve entry API: returns entry by key if still valid.
- Automatic URL detection (
textvsurl). - 10-minute TTL (600 seconds).
- Silent missing behavior for expired/missing keys (
404). - Per-IP rate limiting.
- Swagger UI docs.
- Automated tests with Vitest.
- Next.js 16 (App Router)
- TypeScript
- Upstash Redis / Vercel KV (with local memory fallback when env vars are missing)
- Vitest
src/app/page.tsx: Main UI (Create + Retrieve)src/app/api/entries/route.ts: Create endpoint (POST /api/entries)src/app/api/entries/[key]/route.ts: Retrieve endpoint (GET /api/entries/{key})src/app/api/openapi/route.ts: OpenAPI JSONsrc/app/api/docs/route.ts: Swagger UI HTMLsrc/app/docs/page.tsx: Docs pagesrc/lib/store.ts: Key allocator, expiry, KV/memory logicsrc/lib/rate-limit.ts: Per-IP rate limit logicsrc/lib/openapi.ts: OpenAPI spec builder
- Node.js 18+ (Node 20+ recommended)
- npm
Create .env.local in project root.
Required for Redis/KV mode:
KV_REST_API_URLKV_REST_API_TOKEN
If these are not set, the app runs with in-memory fallback (good for local dev, not for production).
npm installIf your PowerShell policy blocks npm scripts, use:
cmd /c npm.cmd installnpm run devPowerShell-safe variant:
cmd /c npm.cmd run devOpen:
- App:
http://localhost:3000/ - Swagger UI:
http://localhost:3000/docs - OpenAPI JSON:
http://localhost:3000/api/openapi
Run tests:
npm testRun production build:
npm run buildStart production server:
npm run startPOST /api/entries
Request body:
{
"value": "Hello world"
}Success (201):
{
"key": 1
}Validation / error examples:
400if payload invalid orvalueis empty.400if value exceeds 10,000 chars.429if rate limit exceeded.
GET /api/entries/{key}
Success (200):
{
"type": "text",
"value": "Hello world",
"expiresInMs": 534123
}For URL entries:
{
"type": "url",
"value": "https://example.com",
"expiresInMs": 512000
}Missing/expired:
404(silent missing behavior)
Rate limit:
429withRetry-Afterheader
- Max input length: 10,000 chars
- Create rate limit: 20 requests/IP per 60 seconds
- Retrieve rate limit: 90 requests/IP per 60 seconds
- Only store public information.
- Entries expire after 10 minutes and are not recoverable after expiry.
- Key allocator reuses the smallest available positive integer.
- UI:
/docs - JSON:
/api/openapi
- Ensure the same server instance is handling both requests.
- If using KV/Redis, verify
KV_REST_API_URLandKV_REST_API_TOKENare correct. - Restart dev server after changing
.env.local.
Use cmd /c npm.cmd ... as shown above.
Internal project / POC.