From 4864bf630482e2dab81b398a71d9ef697d7d8e51 Mon Sep 17 00:00:00 2001 From: Adriano Belisario Date: Sun, 3 May 2026 18:29:38 +0000 Subject: [PATCH] chore: add data snapshot, deployment compose, and CLAUDE.md - Commit SQLite db snapshot (WAL checkpointed before copy) - Replace upstream docker-compose with real deployment config - Add CLAUDE.md documenting customization and deploy steps - Gitignore secrets.json and SQLite temp files Co-Authored-By: Claude Sonnet 4.6 --- .gitignore | 6 ++- CLAUDE.md | 123 ++++++++++++++++++++++++++++++++++++++++++++ data/db/wishlist.db | Bin 0 -> 53248 bytes docker-compose.yml | 31 +++++++---- 4 files changed, 148 insertions(+), 12 deletions(-) create mode 100644 CLAUDE.md create mode 100755 data/db/wishlist.db diff --git a/.gitignore b/.gitignore index c28067a..f38672c 100644 --- a/.gitignore +++ b/.gitignore @@ -59,5 +59,7 @@ drizzle/ .vscode/ .idea/ -# data -/data +# data — commit db snapshot but not secrets or SQLite temp files +/data/secrets.json +/data/db/*.db-wal +/data/db/*.db-shm diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..5a153db --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,123 @@ +# Chadebebe — Wishlist App + +Baby shower wishlist site running at `chadebebe.omeu.website`. Built on [Reggio Digital's wishlist app](https://github.com/Reggio-Digital/wishlist). + +## Stack + +- **Next.js 16** (App Router, standalone build) +- **SQLite** via better-sqlite3 + Drizzle ORM +- **Tailwind CSS v4** +- **Docker** with Traefik reverse proxy + +## Repository layout + +``` +src/ ← Next.js source code (this repo) +data/ + db/wishlist.db ← SQLite database (committed as snapshot) + uploads/ ← user-uploaded images (not committed) +docker-compose.yml ← deployment config (builds image + Traefik labels) +Dockerfile ← multi-stage Next.js build +``` + +## Customization + +### Site title and homepage text + +Stored in the `settings` table — edit directly in SQLite or via the admin UI: + +```sql +UPDATE settings SET value = 'My Title' WHERE key = 'siteTitle'; +UPDATE settings SET value = 'My subtitle' WHERE key = 'homepageSubtext'; +``` + +### Wishlists + +Each wishlist has a `slug` (URL path), `name`, `description`, and optional cover image. +Items live in `wishlist_items` linked by `wishlist_id`. + +To inspect or edit data directly: + +```bash +sqlite3 data/db/wishlist.db +``` + +### Locale / language + +UI strings are hardcoded in the source. The PT-BR localization lives in: + +- `app/layout.tsx` — `` and metadata description +- `app/[slug]/page.tsx` — `Intl.NumberFormat('pt-BR', ...)` for prices +- `components/share-button.tsx` — "Compartilhar" label +- `app/lock/page.tsx`, `app/not-found.tsx`, `app/page.tsx` — page copy + +To switch language, update those files and rebuild the image. + +### Admin credentials + +Set via environment variables in `docker-compose.yml`: + +```yaml +- ADMIN_USERNAME=your_username +- ADMIN_PASSWORD=your_password +``` + +## Deployment + +### Prerequisites + +- Docker + Docker Compose +- Traefik running on a `web` Docker network with a `letsencrypt` cert resolver +- Domain pointing to the server + +### First deploy + +```bash +git clone https://git.omeu.website/root/chadebebe.git +cd chadebebe + +# Build the image and start +docker compose up -d --build +``` + +The `data/db/wishlist.db` snapshot committed in the repo will be used as the initial database. On first run the app writes `data/secrets.json` (JWT keys) — this file is gitignored and must not be committed. + +### Updating the app + +```bash +# Pull latest source +git pull + +# Rebuild image and restart container +docker compose up -d --build +``` + +### Database backup + +The database is a single SQLite file. Back it up with: + +```bash +sqlite3 data/db/wishlist.db "PRAGMA wal_checkpoint(FULL);" +cp data/db/wishlist.db data/db/wishlist.db.bak +``` + +To commit a new snapshot to git: + +```bash +sqlite3 data/db/wishlist.db "PRAGMA wal_checkpoint(FULL);" +git add data/db/wishlist.db +git commit -m "chore: update db snapshot" +git push gitea main +``` + +## Local development + +```bash +cd src # if cloned at root level, otherwise you're already here +cp .env.example .env +npm install +npm run db:migrate +npm run dev +``` + +App runs at `http://localhost:3000`. Admin at `/admin`. diff --git a/data/db/wishlist.db b/data/db/wishlist.db new file mode 100755 index 0000000000000000000000000000000000000000..91333f4995ffbcfc4e600ce835f741a03001bdfe GIT binary patch literal 53248 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 Vn@G*fPESYfeH7H6JX(?4{{Rt%r(6I4 literal 0 HcmV?d00001 diff --git a/docker-compose.yml b/docker-compose.yml index bdfd22d..006304b 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,16 +1,27 @@ services: - app: - image: reggiodigital/wishlist:latest - container_name: wishlist + wishlist: + build: . + image: chadebebe-ptbr:latest + container_name: chadebebe restart: unless-stopped - ports: - - "3000:3000" environment: - # User/Group IDs (defaults to 1000:1000, Unraid users set to 99:100) - - PUID=${PUID:-1000} - - PGID=${PGID:-1000} - # Admin credentials - ADMIN_USERNAME=${ADMIN_USERNAME:-admin} - ADMIN_PASSWORD=${ADMIN_PASSWORD:-changeme} + - PUID=${PUID:-1000} + - PGID=${PGID:-1000} + - COOKIE_SECURE=true volumes: - - /folder-for-wishlist-data:/app/data + - ./data:/app/data + networks: + - web + labels: + - "traefik.enable=true" + - "traefik.http.routers.chadebebe.rule=Host(`chadebebe.omeu.website`)" + - "traefik.http.routers.chadebebe.entrypoints=https" + - "traefik.http.routers.chadebebe.tls=true" + - "traefik.http.routers.chadebebe.tls.certresolver=letsencrypt" + - "traefik.http.services.chadebebe.loadbalancer.server.port=3000" + +networks: + web: + external: true