Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Big Buys

A private, two-person (Yusuf & Sumayyah) purchase-planning app for big-ticket items. Wishlist items each have a budget cap; candidate listings are logged against them with price history, pros/cons, and per-person ratings/priority votes.

This repo is the real, persistent implementation (Node/Express + SQLite API, React/Vite frontend) built from the original Big Buys.dc.html design prototype, packaged as a single Docker image for a self-hosted NAS.

Stack

  • Backend: Node.js + Express, SQLite via better-sqlite3 (single file DB, no separate database container).
  • Frontend: React + Vite, built to static assets and served by the same Express server — one container, one port.
  • Auth: no real accounts. A client-side Yusuf/Sumayyah profile picker (stored in localStorage) decides whose vote is being set. Optionally gate the whole app behind a shared passphrase (see below) since it's a private tool that may end up reachable on the open internet.
  • Sync: plain REST, refetch-on-load / refetch-after-mutation. No websockets — fine for two people making occasional edits.

Repo layout

server/          Express API + static file server
  src/
    index.js     app entry point, mounts routes, serves client build
    db.js        SQLite schema (items, candidates, price_history, votes, notes)
    serialize.js turns DB rows into the JSON shape the frontend expects
    routes/
      items.js       /api/items, /api/items/:id, notes, votes
      candidates.js  /api/items/:id/candidates, /api/candidates/:id, purchase
  public/        built frontend assets (generated, not committed)
client/          React + Vite source
  src/
    screens/     Wishlist, Item Detail, Compare, Votes, Add
    styles/      Nocturne design tokens (tokens.css) + app layout (app.css)
Dockerfile       multi-stage build: client build -> server deps -> runtime
docker-compose.yml

API surface

  • GET /api/items — all items with nested candidates, notes, votes
  • POST /api/items — create item { name, iconKey, budgetCap, photoUrl?, notes? }
  • PATCH /api/items/:id — update fields / status (active|later|purchased)
  • DELETE /api/items/:id
  • POST /api/items/:id/notes{ text }
  • PUT /api/items/:id/votes/:profile{ tier: 1|2|3 }, profile is yusuf or sumayyah
  • POST /api/items/:id/candidates{ name, price, link?, photoUrl?, pros?, cons?, ratings? }
  • PATCH /api/candidates/:id — editing price appends a price-history point automatically
  • DELETE /api/candidates/:id
  • POST /api/candidates/:id/purchase — marks the parent item purchased with this candidate's price/today's date
  • GET /api/health

All derived values (best price, budget status, priority rank, sparkline points) are computed client-side from the raw data, same as the design prototype — nothing is stored redundantly.

Local development

# terminal 1 — API on :3000
cd server && npm install && npm run dev

# terminal 2 — Vite dev server on :5173, proxies /api to :3000
cd client && npm install && npm run dev

Open http://localhost:5173.

Building & running with Docker (production)

From the repo root, on the NAS (or anywhere with Docker):

docker compose up -d --build

This builds the frontend, installs the server's native SQLite binding, and starts the container listening on port 3000, with the SQLite file persisted to ./data/bigbuys.db on the host (bind-mounted to /data in the container) — so the data survives container rebuilds/updates.

To update after pulling new code:

docker compose up -d --build

Container state (the DB) is untouched by rebuilds since it lives in the mounted ./data folder, not inside the image.

Environment variables

Variable Default Purpose
PORT 3000 Port the server listens on
HOST 0.0.0.0 Bind address
DATA_DIR /data (in container) Where bigbuys.db is stored
APP_PASSPHRASE unset If set, gates the entire app (API + static files) behind HTTP Basic auth — any username, this password. Recommended if you're not putting the app behind Cloudflare Access or similar, since it has no real accounts.

Deploying on the Ugreen DXP-2800

  1. Install Docker (via UGOS Pro's app store, or Portainer/Container Manager if you prefer a UI) on the NAS.
  2. Copy this repo onto the NAS (e.g. git clone over SSH, or use Container Manager's "build from repo" flow).
  3. From the project folder: docker compose up -d --build.
  4. Confirm it's up: curl http://<nas-ip>:3000/api/health should return {"ok":true}.
  5. Expose it at bigbuys.yusufav.uk using your own reverse proxy — Cloudflare Tunnel (cloudflared) pointed at http://localhost:3000 on the NAS is the simplest option, or port-forward + your router's TLS/cert handling. This app only needs to listen on one port; it has no opinion on how you expose it.
  6. If the tunnel/port-forward makes this reachable from the open internet, set APP_PASSPHRASE in docker-compose.yml and restart — otherwise anyone with the URL can read and edit the wishlist.

Backups

The SQLite file at ./data/bigbuys.db (next to docker-compose.yml) is the only copy of your data. A simple nightly cron job on the NAS is enough:

# crontab -e
0 3 * * * cp /volume1/docker/bigbuys/data/bigbuys.db /volume1/docker/bigbuys/backups/bigbuys-$(date +\%Y\%m\%d).db

Prune old backups periodically (e.g. keep the last 30).

Design system

client/src/styles/tokens.css is the Nocturne design-token sheet ported verbatim from the original prototype's styles.css — colors, spacing, radii, and component classes (.btn, .tag, .seg, .dialog, …) are unchanged. app.css adds the layout-specific classes for the five screens (wishlist list/detail, compare, votes, add) that were inline styles in the .dc.html prototype.

One deliberate deviation from the prototype: the "Add" screen's simulated link-fetch (canned demo copy filled in after a fake 900ms delay) was prototype-only flavor with no real backend behind it. The real app instead asks for Title/Price directly, with the link field kept as an optional attached URL — actual link scraping was out of scope for this build.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages