Skip to content

Commit 846ff64

Browse files
copyleftdevclaude
andcommitted
docs: add project README with quick start, API reference, and configuration guide
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent f5ee8f3 commit 846ff64

1 file changed

Lines changed: 199 additions & 0 deletions

File tree

README.md

Lines changed: 199 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,199 @@
1+
```
2+
_ _ _ _
3+
| |__ ___ ___ | | _| |__ (_)_ __
4+
| '_ \ / _ \ / _ \| |/ / '_ \| | '_ \
5+
| | | | (_) | (_) | <| |_) | | | | |
6+
|_| |_|\___/ \___/|_|\_\_.__/|_|_| |_|
7+
```
8+
9+
**Single-binary webhook inbox. Accept HTTP, store it, show it. No external dependencies.**
10+
11+
---
12+
13+
- **One binary, zero dependencies** — no Postgres, no Redis, no Docker Compose. `scp` it to a box, run it, done.
14+
- **Embedded SQLite** — WAL mode, crash-safe, deterministic resource bounds. Data lives in a single directory.
15+
- **Live dashboard** — built-in SPA with live polling, syntax-highlighted JSON, request inspector with full headers and body.
16+
- **134 tests** — every handler, every edge case, every error path. `cargo test` is the only gate.
17+
- **Tiny footprint** — optimized release build with LTO, stripped symbols, and `panic = abort`.
18+
19+
## Quick Start
20+
21+
```bash
22+
# 1. Build (or download a release binary)
23+
cargo build --release
24+
25+
# 2. Run
26+
./target/release/hookbin serve --port 8080
27+
28+
# 3. Create a hook and send a webhook
29+
curl -s http://localhost:8080/api/hooks -X POST | jq .
30+
# => { "id": "abc123xyz", "url": "/h/abc123xyz", ... }
31+
32+
curl -X POST http://localhost:8080/h/abc123xyz \
33+
-H "Content-Type: application/json" \
34+
-d '{"event": "deploy", "status": "success"}'
35+
# => 200 OK
36+
37+
# 4. Open http://localhost:8080 to see it in the dashboard
38+
```
39+
40+
## Dashboard
41+
42+
The embedded dashboard provides a complete webhook inspection UI — no separate frontend service needed.
43+
44+
- **Hook list** with request counts and creation timestamps
45+
- **Request timeline** with method badges and relative timestamps
46+
- **Request inspector** — headers, body, query params, and metadata
47+
- **Syntax-highlighted JSON** with collapsible body viewer
48+
- **Live polling** — new requests appear automatically
49+
- **Responsive layout** — works on desktop and mobile
50+
51+
## API Endpoints
52+
53+
| Method | Path | Description |
54+
|--------|------|-------------|
55+
| `POST` | `/h/{hook_id}` | Ingest a webhook (the money endpoint) |
56+
| `GET` | `/api/hooks` | List all hooks |
57+
| `POST` | `/api/hooks` | Create a new hook |
58+
| `GET` | `/api/hooks/{id}` | Get hook details |
59+
| `DELETE` | `/api/hooks/{id}` | Delete a hook |
60+
| `GET` | `/api/hooks/{id}/requests` | List captured requests |
61+
| `GET` | `/api/hooks/{id}/requests/{rid}` | Get a single request |
62+
| `GET` | `/health` | Health check |
63+
| `GET` | `/` | Dashboard (embedded SPA) |
64+
65+
All API endpoints return structured JSON with error suggestions:
66+
67+
```json
68+
{
69+
"error": "not found: hook abc123xyz",
70+
"suggestion": "Check the hook ID and try again"
71+
}
72+
```
73+
74+
## Configuration
75+
76+
Three-layer config: **defaults** -> **TOML file** -> **CLI flags** (CLI always wins).
77+
78+
### CLI Flags
79+
80+
```bash
81+
hookbin serve [OPTIONS]
82+
```
83+
84+
| Flag | Default | Description |
85+
|------|---------|-------------|
86+
| `--port` | `3000` | Port to listen on |
87+
| `--data` | `./hookbin-data` | Data directory for SQLite database |
88+
| `--max-hooks` | `100` | Maximum number of hooks |
89+
| `--max-payload` | `1048576` | Maximum payload size in bytes (1 MB) |
90+
| `--retention` | `86400` | Request retention in seconds (24 hours) |
91+
| `--rate-limit` | `60` | Rate limit per hook (requests/minute) |
92+
| `--max-requests` | `1000` | Max stored requests per hook |
93+
| `--config` || Path to TOML config file |
94+
95+
### TOML Config
96+
97+
```toml
98+
# hookbin.toml
99+
port = 8080
100+
data = "/var/lib/hookbin"
101+
max_hooks = 50
102+
max_payload = 2097152
103+
retention = 172800
104+
rate_limit = 120
105+
max_requests = 500
106+
```
107+
108+
```bash
109+
hookbin serve --config hookbin.toml
110+
```
111+
112+
## Resource Limits
113+
114+
Hookbin follows the [TigerBeetle philosophy](https://tigerbeetle.com/): deterministic resource usage, pre-allocated bounds, no surprise OOM.
115+
116+
| Resource | Default | Configurable |
117+
|----------|---------|--------------|
118+
| Max hooks | 100 | `--max-hooks` |
119+
| Max payload size | 1 MB | `--max-payload` |
120+
| Request retention | 24 hours | `--retention` |
121+
| Rate limit per hook | 60 req/min | `--rate-limit` |
122+
| Max requests per hook | 1,000 | `--max-requests` |
123+
| SQLite WAL mode | Always on ||
124+
125+
Everything is bounded. Nothing grows without limit.
126+
127+
## Build from Source
128+
129+
```bash
130+
# Prerequisites: Rust stable toolchain
131+
git clone https://github.com/copyleftdev/hookbin.dev.git
132+
cd hookbin.dev
133+
134+
# Development
135+
cargo build # Debug build
136+
cargo test # Run all tests
137+
cargo run -- serve # Run locally on :3000
138+
139+
# Release
140+
cargo build --release # Optimized binary
141+
ls -lh target/release/hookbin
142+
```
143+
144+
### Make Targets
145+
146+
| Target | Description |
147+
|--------|-------------|
148+
| `make build` | Debug build |
149+
| `make release` | Optimized release build |
150+
| `make test` | Run all tests |
151+
| `make fmt` | Format code |
152+
| `make clippy` | Run linter |
153+
| `make check` | Full pre-commit (fmt + clippy + test + build) |
154+
| `make run` | Run server on :8080 |
155+
| `make dev` | Run with `./data` directory |
156+
| `make size` | Show release binary size |
157+
| `make clean` | Remove build artifacts |
158+
159+
## Project Structure
160+
161+
```
162+
src/
163+
main.rs # Entry point, CLI parsing
164+
server.rs # Axum router + server setup
165+
db.rs # SQLite connection, migrations, queries
166+
models.rs # Hook, Request structs
167+
config.rs # CLI args + TOML config (3-layer merge)
168+
error.rs # AppError with structured suggestions
169+
retention.rs # Background cleanup task
170+
rate_limit.rs # In-process token bucket
171+
handlers/
172+
ingest.rs # POST /h/{hook_id} — capture webhook
173+
hooks.rs # CRUD hooks
174+
requests.rs # List/inspect requests
175+
dashboard.rs # Serve embedded UI
176+
health.rs # Health check
177+
ui/
178+
index.html # Dashboard SPA
179+
assets/
180+
app.js # Vanilla JS — hash routing, live polling
181+
style.css # Dashboard styles
182+
```
183+
184+
## Tech Stack
185+
186+
| Component | Implementation |
187+
|-----------|---------------|
188+
| Language | Rust (stable) |
189+
| HTTP server | Axum 0.8 + Tokio |
190+
| Storage | SQLite via rusqlite (bundled, WAL mode) |
191+
| UI embedding | rust-embed (compiled into binary) |
192+
| CLI | clap 4 |
193+
| Serialization | serde + serde_json |
194+
| Error handling | thiserror |
195+
| Logging | tracing + tracing-subscriber |
196+
197+
## License
198+
199+
MIT

0 commit comments

Comments
 (0)