{"id":50749406,"url":"https://github.com/darious/snibox-next","last_synced_at":"2026-06-11T00:01:58.485Z","repository":{"id":359343296,"uuid":"1245412856","full_name":"darious/snibox-next","owner":"darious","description":"Self-hosted snippets/notes/links library — Go + templ/HTMX + SQLite, deployed via docker.","archived":false,"fork":false,"pushed_at":"2026-05-21T12:46:48.000Z","size":124,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-21T20:51:45.128Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/darious.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","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-05-21T07:42:46.000Z","updated_at":"2026-05-21T12:46:54.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/darious/snibox-next","commit_stats":null,"previous_names":["darious/snibox-next"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/darious/snibox-next","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/darious%2Fsnibox-next","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/darious%2Fsnibox-next/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/darious%2Fsnibox-next/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/darious%2Fsnibox-next/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/darious","download_url":"https://codeload.github.com/darious/snibox-next/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/darious%2Fsnibox-next/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34175887,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-10T02:00:07.152Z","response_time":89,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":[],"created_at":"2026-06-11T00:01:57.646Z","updated_at":"2026-06-11T00:01:58.479Z","avatar_url":"https://github.com/darious.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# snibox-next\n\nSelf-hosted, single-user snippets / notes / links library. Modern dark-mode\nreimagining of [snibox/snibox](https://github.com/snibox/snibox). Single\nstatic binary, single SQLite file, HTMX UI, deployed behind your existing\nreverse proxy.\n\nSee [`SPEC.md`](SPEC.md) for the full design spec.\n\n## Stack\n\n- Go 1.22+ (`net/http` + chi)\n- [`a-h/templ`](https://templ.guide) HTML components, HTMX 2.x for interactivity\n- SQLite via `modernc.org/sqlite` (pure-Go, CGO-free — no toolchain headaches)\n- `yuin/goldmark` markdown, `alecthomas/chroma` syntax highlighting (server-side, class mode)\n- All assets embedded via `embed.FS`\n\n## Auth (read this first)\n\n**Auth is out of scope.** v1 trusts whoever can reach the port. The binary\nrefuses to bind to a non-loopback address unless you pass `--trust-network`\n— see [SPEC §1.1](SPEC.md#11-auth-assumption-v1).\n\nDeploy behind a reverse proxy that handles authentication:\nnginx-proxy-manager, Authelia/Authentik, Caddy `basic_auth`, or a Tailscale-only\ningress. No login UI, no session table, no CSRF logic. If you need multi-user,\nfork it — don't bolt it on.\n\n## Quick start (local)\n\n```sh\ngo install github.com/a-h/templ/cmd/templ@latest\ntempl generate\ngo run ./cmd/snibox --seed-demo\n```\n\nOpens on `http://127.0.0.1:8979`. Adds 20 demo items on first boot.\n\n## Production deployment\n\nThe repo ships a `docker-compose.yml` tuned for the **q-docker** stack\npattern (port-published, on the external `web` network, WUD watch labels,\nbind-mount under `/mnt/config/q-docker/service-data/`).\n\n### 1. Pull the image\n\nThe release workflow publishes multi-arch (`amd64` + `arm64`) images to\nGHCR on every push to `main` and on `v*` tags.\n\n```\nghcr.io/darious/snibox-next:latest\nghcr.io/darious/snibox-next:v0.1.0\nghcr.io/darious/snibox-next:sha-\u003cshort\u003e\n```\n\nGHCR images are public; no `docker login` needed to pull.\n\n### 2. Stack drop-in\n\nCopy `docker-compose.yml` into `/mnt/config/q-docker/stacks/snibox-next/`\n(Dockge will manage it). The compose file:\n\n- Pulls `ghcr.io/darious/snibox-next:latest`\n- Binds `/mnt/config/q-docker/service-data/snibox-next` → `/data`\n- Publishes `:8979`\n- Joins the external `web` network so nginx-proxy-manager can reach it\n- Labels `wud.watch=true` so WUD notifies on new digests\n- Sets `SNIBOX_TRUST_NETWORK=true` (the container binds `0.0.0.0`)\n\n```sh\nmkdir -p /mnt/config/q-docker/service-data/snibox-next\nchown 10001:10001 /mnt/config/q-docker/service-data/snibox-next   # container uid\ncd /mnt/config/q-docker/stacks/snibox-next\ndocker compose up -d\n```\n\nThe container runs as uid `10001` (non-root). If the bind-mount isn't\nwritable by that uid the app crashes with\n`open db: unable to open database file (14)` — fix with the `chown` above.\n\n### 3. nginx-proxy-manager host rule\n\n| Field | Value |\n|---|---|\n| Domain | `snibox.lan` (or whatever) |\n| Forward Hostname / IP | `snibox-next` (container name on `web` network) |\n| Forward Port | `8979` |\n| Block Common Exploits | on |\n| Websockets Support | on |\n| Access List | **set one** — that is the auth layer |\n\nAdd TLS via Let's Encrypt as you do for the other services.\n\n### Bare-metal alternative (no Docker)\n\nIf you'd rather run the binary directly:\n\n```sh\n# build\nCGO_ENABLED=0 go build -trimpath \\\n    -ldflags=\"-s -w -X main.Version=$(git describe --tags --always)\" \\\n    -o /usr/local/bin/snibox ./cmd/snibox\n\n# systemd unit (/etc/systemd/system/snibox.service)\n[Unit]\nDescription=snibox-next\nAfter=network-online.target\n\n[Service]\nType=simple\nUser=snibox\nWorkingDirectory=/var/lib/snibox\nExecStart=/usr/local/bin/snibox --addr 127.0.0.1:8979 --db /var/lib/snibox/snibox.db\nRestart=on-failure\nRestartSec=5\n\n[Install]\nWantedBy=multi-user.target\n```\n\n## Flags / env\n\n| Flag | Env | Default | Effect |\n|------|-----|---------|--------|\n| `--addr` | `SNIBOX_ADDR` | `127.0.0.1:8979` | Listen address. |\n| `--db` | `SNIBOX_DB` | `./snibox.db` | SQLite database path. |\n| `--seed-demo` | `SNIBOX_SEED_DEMO` | `false` | Import 20 demo items into an empty DB. Dev/preview only. |\n| `--read-only` | `SNIBOX_READ_ONLY` | `false` | Block all writes (`POST`/`PUT`/`PATCH`/`DELETE`/`/import`). |\n| `--trust-network` | `SNIBOX_TRUST_NETWORK` | `false` | Permit non-loopback bind. Set when behind Docker / a proxy. |\n| `--version` | — | — | Print version and exit. |\n\n## Backup \u0026 restore\n\nThe whole app is one SQLite file (`/data/snibox.db` in the container).\nThree safe options:\n\n### A. Online backup with `sqlite3`\n\nRecommended — works while snibox is running.\n\n```sh\ndocker exec snibox-next sh -c \\\n  'apk add --no-cache sqlite \u003e/dev/null 2\u003e\u00261; \\\n   sqlite3 /data/snibox.db \".backup /data/snibox-$(date +%F).bak\"'\n```\n\nThis uses SQLite's online backup API and is safe with WAL.\n\n### B. `VACUUM INTO`\n\nCompacts and atomically writes a fresh file:\n\n```sh\ndocker exec snibox-next sh -c \\\n  'sqlite3 /data/snibox.db \"VACUUM INTO '\"'\"'/data/snibox-$(date +%F).db'\"'\"'\"'\n```\n\n### C. JSON export\n\nFor a human-readable, version-controllable snapshot:\n\n```sh\ncurl -s http://localhost:8979/export.json \u003e snibox-$(date +%F).json\n```\n\nRestore via `POST /import?mode=replace` with the JSON body. Timestamps are\npreserved per [SPEC §6.2](SPEC.md#62-import).\n\n### Restoring from a `.bak` / `.db`\n\nStop the container, replace the file, start again:\n\n```sh\ndocker compose down snibox-next\ncp snibox-2026-05-21.bak /mnt/config/q-docker/service-data/snibox-next/snibox.db\ndocker compose up -d snibox-next\n```\n\n## Upgrading\n\nIf you're on `:latest`, WUD notifies you of new digests; pull + recreate:\n\n```sh\ndocker compose pull snibox-next\ndocker compose up -d snibox-next\n```\n\nMigrations run automatically on boot from the embedded `migrations/`\ndirectory; existing rows are untouched.\n\n## Development\n\n```sh\ntempl generate                          # rebuild .templ → .go\ngo test ./... -race -cover              # full test suite\ngo build -o snibox ./cmd/snibox         # single binary\n```\n\nTests hit a real SQLite database (in-memory). No mocks.\n\n- `internal/store` — repo unit tests, ~78% covered\n- `internal/importer` — JSON import/export, ~89% covered\n- `internal/handlers` — HTTP route tests through `httptest.Server`, ~60% covered\n\n## Project layout\n\n```\ncmd/snibox/             entrypoint (flags, server boot, --version)\ninternal/\n  store/                repo + migrations + sqlite triggers\n  handlers/             chi routes + HTMX content-negotiation + middleware\n  views/                templ components (page + partials)\n  importer/             JSON import/export\n  markdown/             goldmark + chroma wrappers\n  id/                   ULID helper\n  assets/               embed.FS for static + seed.json\ndocs/reference/         original prototype HTML/JSX/CSS (read-only reference)\n```\n\n## License\n\nMIT — see [LICENSE](LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdarious%2Fsnibox-next","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdarious%2Fsnibox-next","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdarious%2Fsnibox-next/lists"}