diff --git a/README.md b/README.md index 0412bd6..0760912 100644 --- a/README.md +++ b/README.md @@ -1 +1,108 @@ -Personal **VALORANT** Friendbook :3 \ No newline at end of file +# Val-Friendbook + +A small self-hosted friendbook for the lovely peeps I meet on there. Everyone can submit their own page (name, fun fact, favorite color, mood, badge images, ...). New entries stay hidden until an admin approves them. + +Plain Express + Multer, with a JSON file as the "database". No native modules, no external services. + +## Features + +- Public gallery of approved entries, newest first +- Submission form with up to 5 badge images per entry (PNG, JPG, GIF, WEBP, max. 3 MB each; easily my favourite feature lol) +- Moderation: new entries are `pending` until approved in the admin panel +- Denying an entry deletes it and its uploaded images +- Admin panel at `/admin`, protected by a password + +## Requirements + +- Node.js 18 or newer + +## Quick start + +```bash +git clone https://gitea.nkelabs.xyz/nke4/Val-Friendbook.git +cd Val-Friendbook +npm install +ADMIN_PASSWORD='choose-a-strong-password' npm start +``` + +The app runs on `http://localhost:3030` by default. + +## Configuration + +| Variable | Default | Description | +| ---------------- | ---------- | --------------------------------------------------------- | +| `ADMIN_PASSWORD` | `changeme` | Password for the admin panel. **Always set this.** | +| `PORT` | `3030` | Port the server listens on (the Dockerfile sets `3000`). | + +If `ADMIN_PASSWORD` is not set, the server falls back to `changeme` and prints a warning in the log on startup. + +## Deployment + +### pm2 + +```bash +ADMIN_PASSWORD='choose-a-strong-password' PORT=3000 pm2 start server.js --name friendbook +pm2 save +``` + +To change the environment of an existing process: + +```bash +ADMIN_PASSWORD='new-password' pm2 restart friendbook --update-env +pm2 save +``` + +### Docker + +```bash +docker build -t val-friendbook . +docker run -d --name val-friendbook \ + -p 3000:3000 \ + -e ADMIN_PASSWORD='choose-a-strong-password' \ + -v "$(pwd)/data:/app/data" \ + -v "$(pwd)/uploads:/app/uploads" \ + val-friendbook +``` + +## Data + +| Path | Contents | +| ------------------- | ------------------------------ | +| `data/entries.json` | All entries (pending + approved) | +| `uploads/` | Uploaded badge images | + +Both are created automatically on first start and are excluded from git. Back them up or mount them as volumes so entries survive restarts and redeploys. + +## Admin panel + +Open `/admin` and log in with `ADMIN_PASSWORD`. From there you can approve or deny pending entries. + +## API + +| Method | Route | Auth | Description | +| ------ | ---------------------------------- | ----- | ---------------------------------------- | +| GET | `/api/entries` | - | List approved entries | +| POST | `/api/entries` | - | Submit a new entry (multipart, `badges`) | +| POST | `/api/admin/login` | admin | Check the admin password | +| GET | `/api/admin/entries` | admin | List all entries | +| POST | `/api/admin/entries/:id/approve` | admin | Approve an entry | +| POST | `/api/admin/entries/:id/deny` | admin | Delete an entry and its images | + +Admin routes expect the password in the `x-admin-password` header. + +## Project structure + +``` +. +├── server.js # Express backend, JSON storage, admin routes +├── public/ # Frontend (index, admin panel, styles, scripts) +├── Dockerfile +└── package.json +``` + +## Notes + +- The admin password is sent in a header on every admin request. Run the app behind HTTPS (reverse proxy or tunnel) when exposing it publicly. +- Entries are stored in a single JSON file, which is fine for a small friend group but not meant for large scale, any help with this is appreciated, since I can't code for shit + +## Enjoy! :3 \ No newline at end of file