{"id":50127602,"url":"https://github.com/devforth/wait0","last_synced_at":"2026-05-23T20:35:11.730Z","repository":{"id":337203334,"uuid":"1152486007","full_name":"devforth/wait0","owner":"devforth","description":"Instant cache-first HTTP proxy for SSR. Serves dynamic HTML from RAM now, revalidates in background.","archived":false,"fork":false,"pushed_at":"2026-03-05T13:44:51.000Z","size":203,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-23T20:35:05.254Z","etag":null,"topics":["cache","proxy","reverse-proxy","server-side-rendering","speedup"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/devforth.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-02-08T00:04:24.000Z","updated_at":"2026-04-01T09:59:43.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/devforth/wait0","commit_stats":null,"previous_names":["devforth/wait0"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/devforth/wait0","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/devforth%2Fwait0","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/devforth%2Fwait0/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/devforth%2Fwait0/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/devforth%2Fwait0/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/devforth","download_url":"https://codeload.github.com/devforth/wait0/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/devforth%2Fwait0/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33412082,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-23T18:09:33.147Z","status":"ssl_error","status_checked_at":"2026-05-23T18:09:31.380Z","response_time":53,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cache","proxy","reverse-proxy","server-side-rendering","speedup"],"created_at":"2026-05-23T20:35:09.860Z","updated_at":"2026-05-23T20:35:11.721Z","avatar_url":"https://github.com/devforth.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# wait0\n\n\u003e Ultra-fast cache-first reverse proxy for dynamic SSR workloads.\n\n`wait0` serves cached HTML instantly and revalidates in the background.\nIt is designed for Next.js/Nuxt.js and other dynamic origins where latency and origin offload matter.\n\n- GitHub: https://github.com/devforth/wait0\n- Docker Hub: https://hub.docker.com/r/devforth/wait0\n\n## Why wait0\n\n- Instant cached responses with background revalidation (SWR-like flow)\n- Built for dynamic pages, not static asset caching\n- RAM + LevelDB cache tiers for low latency and persistence\n- Async invalidation API with bearer auth and tag support\n- Built-in Basic-Auth dashboard for stats, charts, and invalidation\n- Warmup and sitemap discovery to reduce cold-start misses\n- Explicit response marker `X-Wait0` (`hit`, `miss`, `bypass`, etc.)\n\n## Quick Start\n\n1. Create `wait0.yaml`:\n\n```yaml\nstorage:\n  ram:\n    max: '100m'\n  disk:\n    max: '1g'\n\nserver:\n  port: 8082\n  origin: 'http://localhost:8080'\n\nrules:\n  - match: PathPrefix(/)\n    priority: 1\n    expiration: '1m'\n```\n\n2. Run `wait0` via Docker:\n\n```bash\ndocker run --rm -p 8082:8082 \\\n  -v \"$(pwd)/wait0.yaml:/wait0.yaml:ro\" \\\n  devforth/wait0:latest\n```\n\n3. Alternative: build a tiny wrapper image with your config baked in.\n\n`Dockerfile`:\n\n```dockerfile\nFROM devforth/wait0:latest\nCOPY wait0.yaml /wait0.yaml\nEXPOSE 8082\n```\n\nBuild and run:\n\n```bash\ndocker build -t my-wait0:latest .\ndocker run --rm -p 8082:8082 my-wait0:latest\n```\n\n4. Send requests through wait0:\n\n```bash\ncurl -i http://localhost:8082/\n```\n\nFirst request is usually `X-Wait0: miss`, subsequent requests are usually `X-Wait0: hit`.\n\n## Invalidation Example\n\n```bash\ncurl -i \\\n  -X POST \"http://localhost:8082/wait0/invalidate\" \\\n  -H \"Authorization: Bearer ${WAIT0_INVALIDATION_TOKEN}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"paths\":[\"/products/123\"],\"tags\":[\"product:123\"]}'\n```\n\nReturns `202 Accepted` and processes invalidation asynchronously.\nAuthorization is scope-based (`invalidation:write`) to support least-privilege tokens and future API growth without changing token model.\n\n## Stats API Example\n\n```bash\ncurl -i \\\n  \"http://localhost:8082/wait0\" \\\n  -H \"Authorization: Bearer ${WAIT0_STATS_TOKEN}\"\n```\n\nReturns `200 OK` with cache/memory/refresh/sitemap metrics snapshot.\nAuthorization is scope-based (`stats:read`).\n\n## Dashboard Example\n\nSet dashboard credentials in environment:\n\n```bash\nexport WAIT0_DASHBOARD_USERNAME='ops'\nexport WAIT0_DASHBOARD_PASSWORD='change-me'\n```\n\nOpen:\n\n```text\nhttp://localhost:8082/wait0/dashboard\n```\n\nNotes:\n\n- The dashboard is Basic-Auth protected and disabled when either env variable is missing.\n- The dashboard reads stats and triggers invalidation through server-side bridge handlers.\n- Bearer tokens are not exposed to browser JavaScript.\n- Dashboard invalidation is CSRF-protected (same-origin + token check) and dashboard routes are rate-limited per IP.\n\n## Documentation\n\n| Guide | Description |\n|-------|-------------|\n| [For Developers](docs/for-developers.md) | Build/test commands, config reference, runtime options |\n| [API Endpoints](docs/api-endpoints.md) | Proxy behavior, invalidation API, schemas, status codes |\n\n## Redeploy Note\n\nSSR frameworks like Next.js/Nuxt usually output versioned static asset names (for example, `app.abc123.js`).\nAfter a redeploy, HTML references switch to new filenames (for example, `app.def456.js`), and old files are commonly removed.\n\nIf stale HTML is still cached, clients can receive pages that point to missing assets. Typical symptoms are broken UI, hydration failures, and partial renders.\n\nTo reduce this risk, `wait0` clears disk cache on startup by default (`WAIT0_INVALIDATE_DISK_CACHE_ON_START=true`).\nThat behavior makes rollout safer because old HTML is not reused across deploy generations.\n\nIf you do not restart between deploys, proactively refresh cache using invalidation and warmup for critical routes.\n\n## Under the Hood\n\n- Request pipeline: RAM cache -\u003e disk cache -\u003e origin.\n- Cache key is path-only (query and fragment are ignored for cache identity).\n- Only `GET` requests are cache candidates.\n- Only origin `2xx` responses are stored.\n- For stale entries (rule `expiration`), wait0 serves cached response immediately and revalidates asynchronously.\n- For origin non-`2xx`, wait0 skips caching and evicts any existing key for that path.\n- Invalidation is asynchronous: accept request -\u003e resolve keys by `paths` and `tags` -\u003e delete keys -\u003e recrawl in background.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdevforth%2Fwait0","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdevforth%2Fwait0","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdevforth%2Fwait0/lists"}