slwishes.com repo backup and version history
  • JavaScript 94.6%
  • LSL 2.3%
  • PLpgSQL 2.1%
  • CSS 0.7%
  • Dockerfile 0.3%
Find a file
2026-06-11 14:58:29 -04:00
backend Updated the Refresh Prices into a modal among other changes 2026-06-11 14:58:29 -04:00
frontend Updated the Refresh Prices into a modal among other changes 2026-06-11 14:58:29 -04:00
lslScripts Updated the Refresh Prices into a modal among other changes 2026-06-11 14:58:29 -04:00
.env Updated the Refresh Prices into a modal among other changes 2026-06-11 14:58:29 -04:00
.env.example initial commit 2026-04-23 18:28:37 -04:00
.gitignore changed default page count and added .gitignore 2026-04-28 05:11:33 -04:00
docker-compose.yml Updated the Refresh Prices into a modal among other changes 2026-06-11 14:58:29 -04:00
README.md initial commit 2026-04-23 18:28:37 -04:00

SLWishes 🎁

A self-hosted Second Life Marketplace wishlist sharing app.

Share your wishlist at: https://slwishes.yourdomain.com/share/kat.morningstar


Stack

  • Backend — Node.js 22 + Express (ESM)
  • Frontend — Next.js 14 (App Router)
  • Database — Your existing PostgreSQL container (172.29.0.50)
  • Networking — Joins your existing nginx Docker network

Setup

1. Create the database

Connect to your existing Postgres and create the database:

CREATE DATABASE slwishes;

Then run the migration:

psql -h 172.29.0.50 -U apenwell -d slwishes -f backend/migrations/001_initial.sql

Or from inside Docker after the backend starts:

docker exec slwishes-backend node src/db/migrate.js

2. Configure environment

cp .env.example .env

Edit .env:

DB_USER=apenwell
DB_PASSWORD=WesterN061092
DB_NAME=slwishes
JWT_SECRET=some_very_long_random_string_change_this
PUBLIC_API_URL=https://slwishes.yourdomain.com/api

3. Build & run

docker compose up -d --build

4. Nginx Proxy Manager

Add two proxy hosts in NPM:

Domain Forward to Port
slwishes.yourdomain.com slwishes-frontend 3000
slwishes.yourdomain.com/api/* slwishes-backend 3001

Or if using a path-based setup, add a custom location /api/http://slwishes-backend:3001.


API Reference

Auth

Method Path Body Notes
POST /api/auth/register {uuid, username, display_name?, pin} Creates avatar + default wishlist, returns session token
POST /api/auth/login {identifier, pin} identifier = username or UUID
POST /api/auth/logout Invalidates session

Public

Method Path Notes
GET /api/share/:identifier identifier = username or UUID; auto-redirects UUID → username
POST /api/items/:id/gift {purchased_by?} — public endpoint, no auth needed

Authenticated (Bearer token required)

Method Path Notes
GET /api/avatar/me Your profile
PATCH /api/avatar/me Update display_name
POST /api/avatar/me/change-pin {current_pin, new_pin}
PATCH /api/wishlist {title?, description?, is_public?}
POST /api/items Add item
POST /api/items/scrape {url} — scrape MP listing and return prefilled data
PATCH /api/items/:id Update item
DELETE /api/items/:id Remove item
GET /api/webhooks List your webhooks
POST /api/webhooks {type, url, events[], label?}
PATCH /api/webhooks/:id Update webhook
DELETE /api/webhooks/:id Delete webhook

Webhook Events

Event Fires when
item_gifted Someone marks an item as gifted
item_added Owner adds a new item
item_removed Owner removes an item
wishlist_updated Wishlist title/description changed

Discord webhooks send rich embeds. Generic webhooks send:

{ "event": "item_gifted", "payload": { ... }, "timestamp": "..." }

Item Priority

Set priority (010) on items. Items with priority > 5 show a ★ High Priority badge on the share page.


Notes on the Scraper

The scraper (POST /api/items/scrape) fetches the SL Marketplace page and extracts name, price, image, and store info. SL Marketplace occasionally changes its HTML structure; if scraping fails, the frontend falls back to manual entry gracefully.


Frontend Pages

URL Description
/ Landing page
/register Create account
/login Sign in
/dashboard Manage your items, webhooks, settings
/share/:identifier Public wishlist view (username or UUID)