Initial commit
This commit is contained in:
102
README.md
Normal file
102
README.md
Normal file
@@ -0,0 +1,102 @@
|
||||
# Veola
|
||||
|
||||
Self-hosted Go web app that tracks items across e-commerce platforms (eBay, Amazon family, Yahoo Auctions JP, Mercari JP) via the [Apify](https://apify.com) scraping API and pushes deal alerts to a self-hosted [ntfy](https://ntfy.sh) instance.
|
||||
|
||||
Track. Watch. Notice.
|
||||
|
||||
## Features
|
||||
|
||||
- Watch arbitrary items across multiple marketplaces with per-item search queries, target prices, and poll intervals
|
||||
- Active-listing, sold-listing, and price-comparison actors per item
|
||||
- Price-history chart and best-price badge once enough history accumulates
|
||||
- Deal alerts pushed to ntfy when current price falls at or below target
|
||||
- Single-binary deploy, SQLite storage, no CGO
|
||||
|
||||
See [`veola-spec.md`](veola-spec.md) for the full specification.
|
||||
|
||||
## Requirements
|
||||
|
||||
- Go 1.22+ (developed against 1.25)
|
||||
- An [Apify](https://apify.com) account + API key
|
||||
- A reachable [ntfy](https://ntfy.sh) instance (self-hosted or ntfy.sh)
|
||||
|
||||
## Build
|
||||
|
||||
```sh
|
||||
go build -o veola-bin .
|
||||
```
|
||||
|
||||
The binary is named `veola-bin` rather than `veola` because the module is also `veola` — `go build` cannot write a binary with the same name as the module dir.
|
||||
|
||||
If you change any `.templ` files, regenerate first:
|
||||
|
||||
```sh
|
||||
~/go/bin/templ generate
|
||||
```
|
||||
|
||||
## Configure
|
||||
|
||||
Copy the example and edit:
|
||||
|
||||
```sh
|
||||
cp config.toml.example config.toml
|
||||
```
|
||||
|
||||
Both `session_secret` and `encryption_key` must be at least 32 bytes and different from each other. Generate with:
|
||||
|
||||
```sh
|
||||
openssl rand -hex 32
|
||||
```
|
||||
|
||||
`encryption_key` encrypts secrets at rest in SQLite (Apify keys, ntfy settings). Rotating it invalidates stored secrets — re-enter them through `/settings` after rotation.
|
||||
|
||||
## Run
|
||||
|
||||
```sh
|
||||
./veola-bin -config config.toml
|
||||
```
|
||||
|
||||
First-run flow:
|
||||
|
||||
1. Visit `http://localhost:8080/`. With no users, you are redirected to `/setup`.
|
||||
2. Create the admin account.
|
||||
3. Log in at `/login`.
|
||||
4. Add items at `/items/new`. Optionally fill in your Apify key and ntfy URL via `/settings` if you didn't put them in `config.toml`.
|
||||
|
||||
The scheduler starts with the server and polls each active item on its configured interval. The bottom-of-hour global poll runs every `scheduler.global_poll_interval_minutes`.
|
||||
|
||||
## Layout
|
||||
|
||||
```
|
||||
main.go entry point: config, db open, scheduler, http server
|
||||
internal/
|
||||
config/ TOML config loading and validation
|
||||
crypto/ AES-GCM encryption for secrets at rest
|
||||
db/ SQLite schema, migrations, store
|
||||
models/ domain types
|
||||
apify/ Apify API client
|
||||
ntfy/ ntfy push client
|
||||
auth/ session + CSRF
|
||||
scheduler/ poll loop, alert/dedup/badge logic
|
||||
handlers/ HTTP handlers
|
||||
templates/ templ components
|
||||
static/ CSS, vendored htmx
|
||||
```
|
||||
|
||||
## Test
|
||||
|
||||
```sh
|
||||
go test ./...
|
||||
```
|
||||
|
||||
Unit tests cover crypto round-trip, db round-trip and dedup, and scheduler alert/badge logic. No handler-level tests yet.
|
||||
|
||||
## Operate
|
||||
|
||||
- The SQLite file lives at `server.db_path` (default `./veola.db`). Back this up — it holds your watched items, history, encrypted secrets, and user accounts.
|
||||
- The process responds to `SIGINT` / `SIGTERM` with a graceful HTTP shutdown (30s timeout) followed by scheduler stop.
|
||||
- Logs go to stdout as structured `log/slog` records.
|
||||
|
||||
## Aesthetic
|
||||
|
||||
Sega Genesis blue. Not dark mode, not light mode — blue mode. See the visual design section of `veola-spec.md` for the palette.
|
||||
Reference in New Issue
Block a user