README.md (8870B)
1 Bzl is a self-hostable, modular social platform designed for creators and communities who want full control of their space. Launch your own instance, extend it with plugins, and shape the experience to fit your world. 2 3 🔗 Try the live dev instance: https://chat.bzl.one/ 4 5 🚀 Learn more & quick start: https://bzl.one/ 6 7 💬 Follow development in real time: https://chat.bzl.one/ REGISTRATION CODE IS "bzl" 8 9 If you're experimenting, building plugins, or just curious how Bzl works in the wild — jump into the official instance and say hi. 10 11 12 13 # Bzl (MVP) 14 15 Keyword-driven ephemeral posts ("pollination") that auto-expire after a TTL and broadcast live over WebSockets. Each post has a tiny chat room. 16 17 Feed ordering: 18 - Posts rise to the top based on recent chat activity (and manual boosts), not just creation time. 19 - Other users can boost a post (+5m to +2h). Each chat message bumps the post (+2m, capped). 20 - Posts and chat messages support emoji reactions (thumbs-up, heart, angry, sob, pleading, laugh-cry). 21 - Hive feed supports filtering by keywords and author, plus sort modes (`Most recent activity`, `Most popular`, `About to expire`). 22 - Users get private `Starred` and `Hidden` hive views (`⭐` reaction on hives stars them; hidden hives are user-local). 23 - Hives are assigned to curated collections; compose includes a required collection selector and feed supports collection tabs. 24 - Owner/moderator can define custom role tags and gate collections by base/custom role. 25 - Clicking a member in `People` opens their profile view (bio, pronouns, theme song, and social links), with an in-panel editor for the profile owner. 26 27 Media uploads: 28 - GIF/image/audio attachments are uploaded to `data/uploads/` and referenced by short `/uploads/...` URLs. 29 - This avoids massive WebSocket payloads from base64 data URLs and is more reliable for larger files. 30 31 ## Docs 32 33 - Full feature rundown (video script aid): `docs/FUNCTIONALITY_REFERENCE.md` 34 - Plugins (MVP): `docs/PLUGINS.md` 35 - UI rack layout (draft): `docs/UI_RACK_LAYOUT.md` 36 - Directory plugins (draft): `docs/DIRECTORY_SPEC.md` 37 - Moderation spec: `docs/MODERATION_MVP_SPEC.md` 38 - Self-hosted installer plan: `docs/SELF_HOSTED_INSTALLER_PLAN.md` 39 - Multi-instance docker stack: `docs/MULTI_INSTANCE_DOCKER.md` 40 - Instance fleet automation (discovery + bulk update): `docs/INSTANCE_FLEET_AUTOMATION.md` 41 - Issue tracker guide: `docs/ISSUE_TRACKER.md` 42 - Updating a live server (git + docker): `docs/SERVER_UPDATE.md` 43 44 ## Run locally 45 46 ### Docker 47 48 To run a local instance of the app, the following command can be used: 49 ```bash 50 docker compose -f compose.yaml up --build --remove-orphans 51 ``` 52 53 Optionally the `-d` flag can be specified to let the app run as a background process. 54 55 ### Manual 56 57 1. Install Node.js (recommended: Node 18+) 58 2. From this folder: 59 - Optional first-time wizard: `npm run init` (Windows PowerShell: `npm.cmd run init`) 60 - `npm install` (or `npm.cmd install` in Windows PowerShell if `npm` is blocked by execution policy) 61 - `npm start` (or `npm.cmd start` in Windows PowerShell) 62 - Recommended: GUI launcher: `LAUNCHER.cmd` / `LAUNCHER.ps1` (or `npm run launcher:ui`) — includes Cloudflare setup + core auto-update 63 - Or a launcher (opens the URL when ready): `npm run launch` 64 - Or launcher + Cloudflare quick tunnel: `npm run launch:tunnel` 65 3. Open: 66 - `http://localhost:3000` 67 - or from another device on the same Wi-Fi/LAN: `http://<your-laptop-ip>:3000` 68 69 If another device can't connect, allow inbound connections for Node on your firewall. 70 71 Health check endpoint: 72 - `GET /api/health` returns basic runtime status for setup/service checks. 73 - Includes active rate-limit bucket count for diagnostics. 74 75 ## Accounts (username/password) 76 77 Posting and chat require signing in. 78 79 Create users on the host machine (your laptop): 80 - `node scripts/create-user.js <username>` 81 - or `npm.cmd run create-user -- <username>` 82 83 The users file is stored at `data/users.json` on your host (ignored by git). 84 85 First-time setup option: if no users exist yet, you can create the first user from `http://localhost:3000` (loopback only). 86 87 To let other people create their own accounts (useful over a tunnel), set a registration code on the host: 88 - PowerShell (current session): `$env:REGISTRATION_CODE="some-long-random-string"` 89 - Then restart the server. 90 91 ## Backups and restore 92 93 Runtime data can be snapshotted locally (users, posts, reports, mod log, sessions, uploads). 94 95 - Create backup: `npm run backup-data` 96 - List backups: `node scripts/restore-data.js --list` 97 - Restore latest backup: `npm run restore-data -- --yes` 98 - Restore a specific backup: `npm run restore-data -- --name <backup-folder-name> --yes` 99 100 Notes: 101 - Restore overwrites current runtime files in `data/`. 102 - Restore automatically creates a `pre-restore-*` safety snapshot first. 103 104 ## Service reliability (Windows) 105 106 Run with supervision (auto-restart + health watchdog): 107 - `npm run start:supervised` 108 109 Install a startup task for your Windows user: 110 - `powershell -ExecutionPolicy Bypass -File .\\scripts\\install-windows-startup.ps1` 111 112 Remove startup task: 113 - `powershell -ExecutionPolicy Bypass -File .\\scripts\\uninstall-windows-startup.ps1` 114 115 Runner env vars (optional): 116 - `HEALTHCHECK_URL` (default `http://127.0.0.1:<PORT>/api/health`) 117 - `HEALTHCHECK_MS` (default `15000`) 118 - `HEALTHCHECK_TIMEOUT_MS` (default `4000`) 119 - `HEALTHCHECK_FAILS` (default `3`) 120 - `RESTART_MIN_MS` (default `2000`) 121 - `RESTART_MAX_MS` (default `30000`) 122 123 ## Share beyond LAN (tunnel) 124 125 If you want friends to connect from anywhere without port forwarding, run a tunnel on your host PC. 126 127 Cloudflare quick tunnel (no router changes): 128 1. Install: `winget install Cloudflare.cloudflared` 129 2. Start Bzl: `npm.cmd start` 130 3. In a second terminal run: `cloudflared tunnel --url http://localhost:3000` 131 4. Share the `https://...trycloudflare.com` URL it prints. 132 133 If you update the app and someone still sees an older UI, do a hard refresh (or open an incognito window). The server sets `Cache-Control: no-store`, but some browsers/proxies can still hold onto old assets briefly. 134 135 Cloudflare named tunnel (stable URL): 136 1. Put a domain on Cloudflare (DNS managed by Cloudflare). 137 2. Authenticate `cloudflared` (one-time; opens a browser): `cloudflared tunnel login` 138 3. Create the tunnel: `cloudflared tunnel create bzl` 139 4. Route a hostname to it (example): `cloudflared tunnel route dns bzl bzl.yourdomain.com` 140 5. Create a config file at `%HOMEPATH%\\.cloudflared\\config.yml`: 141 - `tunnel: <TUNNEL-UUID>` 142 - `credentials-file: C:\\Users\\<you>\\.cloudflared\\<TUNNEL-UUID>.json` 143 - `ingress:` mapping your hostname to Bzl: 144 - `- hostname: bzl.yourdomain.com` 145 `service: http://localhost:3000` 146 - `- service: http_status:404` 147 6. Run it: 148 - Foreground: `cloudflared tunnel run bzl` (requires the `config.yml` ingress rules) 149 - One-off (no config): `cloudflared tunnel run bzl --url http://localhost:3000` 150 - As a service: `cloudflared service install` (then it starts on boot) 151 152 ## Environment variables 153 154 - `PORT` (default `3000`) 155 - `HOST` (default `0.0.0.0`) 156 - `DEFAULT_TTL_MS` (default `3600000`) 157 - `MIN_TTL_MS` (default `60000`) 158 - `MAX_TTL_MS` (default `172800000`) 159 - `USERS_FILE` (default `data/users.json`) 160 - `POSTS_FILE` (default `data/posts.json`) 161 - `COLLECTIONS_FILE` (default `data/collections.json`) 162 - `ROLES_FILE` (default `data/roles.json`) 163 - `UPLOADS_DIR` (default `data/uploads`) 164 - `IMAGE_UPLOAD_MAX_BYTES` (default `104857600` = 100 MB) 165 - `AUDIO_UPLOAD_MAX_BYTES` (default `157286400` = 150 MB) 166 - `PROFILE_BIO_MAX_HTML_LEN` (default `120000`) 167 - `PROFILE_PRONOUNS_MAX_LEN` (default `40`) 168 - `PROFILE_LINK_LABEL_MAX_LEN` (default `40`) 169 - `PROFILE_LINK_URL_MAX_LEN` (default `280`) 170 - `PROFILE_LINKS_MAX` (default `8`) 171 172 Startup validation: 173 - Server validates critical env values at boot and exits with clear errors if invalid. 174 175 Rate limits: 176 - Auth: login/register/resume session are rate-limited. 177 - Uploads: image/audio uploads are rate-limited per sender. 178 - Moderation: report creation and moderation actions are rate-limited. 179 - Server emits `rateLimited` messages over WebSocket and `429` with `retryMs` for upload API. 180 181 Rate limit env vars: 182 - `RL_LOGIN_WINDOW_MS` (default `60000`) 183 - `RL_LOGIN_MAX` (default `12`) 184 - `RL_REGISTER_WINDOW_MS` (default `600000`) 185 - `RL_REGISTER_MAX` (default `6`) 186 - `RL_RESUME_WINDOW_MS` (default `60000`) 187 - `RL_RESUME_MAX` (default `30`) 188 - `RL_UPLOAD_WINDOW_MS` (default `300000`) 189 - `RL_UPLOAD_IMAGE_MAX` (default `20`) 190 - `RL_UPLOAD_AUDIO_MAX` (default `10`) 191 - `RL_REPORT_WINDOW_MS` (default `600000`) 192 - `RL_REPORT_MAX` (default `12`) 193 - `RL_MOD_WINDOW_MS` (default `60000`) 194 - `RL_MOD_MAX` (default `40`) 195 196 ## Open source 197 198 Bzl is released under the MIT License. See `LICENSE`. 199 200 Community docs: 201 - Contributing: `CONTRIBUTING.md` 202 - Security policy: `SECURITY.md` 203 - Issue tracker guide: `docs/ISSUE_TRACKER.md`