{"id":42865935,"url":"https://github.com/noblepayne/boostbox","last_synced_at":"2026-01-30T12:46:33.646Z","repository":{"id":323290198,"uuid":"1092074928","full_name":"noblepayne/boostbox","owner":"noblepayne","description":"Simple self-hosted service for storing and serving Podcasting 2.0 boost metadata.","archived":false,"fork":false,"pushed_at":"2025-12-12T19:05:27.000Z","size":952,"stargazers_count":5,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-12-13T06:19:41.476Z","etag":null,"topics":["boosts","lightning-network","podcasting","podcasting20"],"latest_commit_sha":null,"homepage":"https://boostbox.cloud","language":"Clojure","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/noblepayne.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-11-08T00:33:29.000Z","updated_at":"2025-12-12T23:26:46.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/noblepayne/boostbox","commit_stats":null,"previous_names":["noblepayne/boostbox"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/noblepayne/boostbox","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/noblepayne%2Fboostbox","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/noblepayne%2Fboostbox/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/noblepayne%2Fboostbox/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/noblepayne%2Fboostbox/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/noblepayne","download_url":"https://codeload.github.com/noblepayne/boostbox/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/noblepayne%2Fboostbox/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28912915,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-30T12:13:43.263Z","status":"ssl_error","status_checked_at":"2026-01-30T12:13:22.389Z","response_time":66,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["boosts","lightning-network","podcasting","podcasting20"],"created_at":"2026-01-30T12:46:32.950Z","updated_at":"2026-01-30T12:46:33.638Z","avatar_url":"https://github.com/noblepayne.png","language":"Clojure","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n  \u003cimg src=\"./images/v4vbox.png\" alt=\"3D box with 'V4V' on one side.\" width=\"128\"\u003e\n\u003c/div\u003e\n\n# BoostBox\n\nA simple, lightweight, and self-hostable API for storing and retrieving [Podcasting 2.0](https://podcasting2.org/) payment metadata.\n\nDemo: [boostbox.cloud](https://boostbox.cloud)\n\nDemo Boost: [01KB19TNRVE1RVQCXVFWY68PYG](https://boostbox.cloud/boost/01KB19TNRVE1RVQCXVFWY68PYG)\n\n![Demo GIF (Jeff)](images/demo.gif)\n\n---\n\n## What is BoostBox?\n\nBoostBox provides a simple API that implements a developing standard for [transmitting payment metadata via HTTP headers](https://github.com/Podcastindex-org/podcast-namespace/pull/734). It allows an application to:\n\n1. Store the full JSON metadata payload with a single `POST` request.\n1. Receive a short, stable URL in return.\n1. Place this URL into the Lightning invoice description.\n\nThis ensures the link to the original boost metadata is preserved with the payment, enabling the full [Value4Value](https://podcasting2.org/docs/podcast-namespace/tags/value) experience.\n\n## How It Works\n\nThe process is designed to be as simple as possible for podcast app developers.\n\n### Step 1: POST Metadata to BoostBox\n\nYour app gathers all the boostagram metadata and sends it as a JSON object to the `/boost` endpoint.\n\n```sh\ncurl -X POST https://boostbox.cloud/boost \\\n  -H \"Content-Type: application/json\" \\\n  -H \"X-Api-Key: v4v4me\" \\\n  -d '{\n    \"action\": \"boost\",\n    \"split\": 1,\n    \"value_msat\": 639000,\n    \"value_msat_total\": 639000,\n    \"timestamp\": \"2025-11-02T16:30:00Z\",\n    \"app_name\": \"My Awesome Player\",\n    \"sender_name\": \"Satoshi\",\n    \"message\": \"Best episode ever!\",\n    \"feed_guid\": \"72d5e069-f907-5ee7-b0d7-45404f4f0aa5\",\n    \"feed_title\": \"LINUX Unplugged\",\n    \"item_guid\": \"4c0a537d-10c6-40ca-b44c-9a43891313c6\",\n    \"item_title\": \"639: The Mess Machine\"\n  }'\n```\n\n### Step 2: Get the Response\n\nBoostBox stores the metadata and returns a URL and a pre-formatted BOLT11 description.\n\n```json\n{\n  \"id\": \"01K9R9E2JNE1CR0ME6CFM45T8E\",\n  \"url\": \"https://boostbox.cloud/boost/01K9R9E2JNE1CR0ME6CFM45T8E\",\n  \"desc\": \"rss::payment::boost https://boostbox.cloud/boost/01K9R9E2JNE1CR0ME6CFM45T8E Best episode ever!\"\n}\n```\n\n### Step 3: Pay the Invoice\n\nYour app uses the `desc` field from the response as the description when paying the podcaster's Lightning Address invoice.\n\n### Step 4: Metadata is Preserved\n\nWhen the podcaster's receiving service (like Helipad, Alby, etc.) gets the payment, it can fetch the URL from the description. BoostBox will respond with the full, original metadata in the `x-rss-payment` HTTP header.\n\n```sh\ncurl -v \"http://boostbox.cloud/boost/01K9R9E2JNE1CR0ME6CFM45T8E\"\n\n\u003e GET /boost/01K9R9E2JNE1CR0ME6CFM45T8E HTTP/1\n\u003e Host: boostbox.cloud\n...\n\n\u003c HTTP/1 200\n\u003c content-type: text/html; charset=UTF-8\n\u003c x-rss-payment: %7B%22message%22%3A%22Best%20episode%...\n...\n\n\u003c!-- The page body will show a human-readable view of the metadata --\u003e\n```\n\n## Getting Started\n\n### Option 1: Run Directly with Nix (No Cloning)\n\nIf you have [Nix](https://nixos.org/download.html) installed with flakes support, you can run BoostBox directly without cloning the repository:\n\n```sh\nnix run github:noblepayne/boostbox\n```\n\nThis will start the server on `http://localhost:8080` with default settings.\n\n### Option 2: Docker\n\n**1. Quick Start (Pre-built Image)**\n\nYou can run the latest version directly from the container registry without building it yourself.\n\nFirst, set up your configuration by copying one of the provided templates to a `.env` file:\n\n- **Filesystem Storage (Simplest):** `cp env.fs.template .env`\n- **S3 Storage:** `cp env.s3.template .env` (edit to add your credentials)\n\nThen run the container:\n\n```sh\ndocker run -p 8080:8080 --env-file .env --name boostbox ghcr.io/noblepayne/boostbox:latest\n```\n\n**2. Using Docker Compose**\n\nIf you prefer Compose, ensure your `.env` file is created (as above), then update the `image` in `docker-compose.yml` to `ghcr.io/noblepayne/boostbox:latest` and run:\n\n```sh\ndocker-compose up\n```\n\n**3. Build from Source (Nix)**\n\nIf you prefer to build the container locally using Nix:\n\n```sh\ngit clone https://github.com/noblepayne/boostbox \u0026\u0026 cd boostbox\nnix build .#container \u0026\u0026 docker load \u003c ./result\n```\n\nThen run using the local tag:\n\n```sh\ndocker run -p 8080:8080 --env-file .env --name boostbox boostbox\n```\n\n### Option 3: Build and Run Locally with Nix\n\n1. Clone the repository: `git clone https://github.com/noblepayne/boostbox`\n1. Change into the directory: `cd boostbox`\n1. Build: `nix build`\n1. Run: `./result/bin/boostbox`\n\nConfigure via environment variables (see Configuration section below).\n\n### Option 4: Develop with Nix\n\nFor REPL-oriented development with Calva (VSCode):\n\n1. Clone the repository: `git clone https://github.com/noblepayne/boostbox`\n1. Change into the directory: `cd boostbox`\n1. Enter the development environment: `./dev.sh`\n1. VSCode will launch automatically with Calva pre-configured\n1. Configure via environment variables (see Configuration section below)\n1. Use Calva to connect to the NREPL and start developing\n\n## Configuration\n\nConfiguration is handled via environment variables.\n\n### Core Configuration\n\n| Variable          | Required | Default                 | Description                                                                                                        |\n| ----------------- | :------: | ----------------------- | ------------------------------------------------------------------------------------------------------------------ |\n| `ENV`             |    No    | `DEV`                   | The runtime environment: `DEV`, `STAGING`, or `PROD`.                                                              |\n| `BB_PORT`         |    No    | `8080`                  | The port the webserver will listen on.                                                                             |\n| `BB_BASE_URL`     |    No    | `http://localhost:8080` | The public base URL of the service (e.g., `https://my-boostbox.com`). Used to construct response URLs.             |\n| `BB_ALLOWED_KEYS` |    No    | `v4v4me`                | Comma-separated list of API keys clients must provide in the `X-Api-Key` header to use the `POST /boost` endpoint. |\n| `BB_MAX_BODY`     |    No    | `102400`                | Maximum allowed size for request bodies in bytes (approximately 100KB by default).                                 |\n| `BB_STORAGE`      |    No    | `FS`                    | The backend for storing metadata: `FS` (filesystem) or `S3`.                                                       |\n\n### Filesystem Storage Configuration\n\n| Variable          | Required | Default  | Description                                                                 |\n| ----------------- | :------: | -------- | --------------------------------------------------------------------------- |\n| `BB_FS_ROOT_PATH` |    No    | `boosts` | If `BB_STORAGE=FS`, the root directory where metadata files will be stored. |\n\n### S3 Storage Configuration\n\nTo use S3 storage (AWS S3, MinIO, or compatible), set `BB_STORAGE=S3` and configure the following:\n\n| Variable           | Required | Default | Description                                                                                                         |\n| ------------------ | :------: | ------- | ------------------------------------------------------------------------------------------------------------------- |\n| `BB_S3_ENDPOINT`   |   Yes    | N/A     | The S3 endpoint URL (e.g., `https://s3.amazonaws.com` or `http://localhost:9000` for MinIO). Must include protocol. |\n| `BB_S3_REGION`     |   Yes    | N/A     | AWS region (e.g., `us-east-1`).                                                                                     |\n| `BB_S3_ACCESS_KEY` |   Yes    | N/A     | S3 access key ID.                                                                                                   |\n| `BB_S3_SECRET_KEY` |   Yes    | N/A     | S3 secret access key.                                                                                               |\n| `BB_S3_BUCKET`     |   Yes    | N/A     | S3 bucket name.                                                                                                     |\n\n### S3 Setup Examples\n\n**Using AWS S3:**\n\n```sh\nexport BB_STORAGE=S3\nexport BB_S3_REGION=us-east-1\nexport BB_S3_ACCESS_KEY=your-aws-access-key\nexport BB_S3_SECRET_KEY=your-aws-secret-key\nexport BB_S3_BUCKET=my-boostbox-bucket\n./result/bin/boostbox\n```\n\n**Using MinIO locally:**\n\n```sh\nexport BB_STORAGE=S3\nexport BB_S3_ENDPOINT=http://localhost:9000\nexport BB_S3_REGION=us-east-1\nexport BB_S3_ACCESS_KEY=minioadmin\nexport BB_S3_SECRET_KEY=minioadmin\nexport BB_S3_BUCKET=boostbox\n./result/bin/boostbox\n```\n\nThe included `flake.nix` dev environment provides MinIO. Run `devenv up` to start it for manual testing. This is done automatically for `./tests.sh`.\n\n## API Quick Reference\n\n### `POST /boost`\n\nStores boostagram metadata.\n\n- **Authentication:** Requires an API key in the `X-Api-Key` header (default: `v4v4me`).\n\n- **Request Body:** A JSON object with the following **required** fields:\n  - `action` (enum: `boost` or `stream`)\n  - `split` (number, min 0.0)\n  - `value_msat` (integer, min 1)\n  - `value_msat_total` (integer, min 1)\n  - `timestamp` (ISO-8601 string)\n\n  Optional fields include: `group`, `message`, `app_name`, `app_version`, `sender_id`, `sender_name`, `recipient_name`, `recipient_address`, `value_usd`, `position`, `feed_guid`, `feed_title`, `item_guid`, `item_title`, `publisher_guid`, `publisher_title`, `remote_feed_guid`, `remote_item_guid`, `remote_publisher_guid`.\n\n- **Success Response (`201 Created`):**\n\n  ```json\n  {\n    \"id\": \"01K9R9E2JNE1CR0ME6CFM45T8E\",\n    \"url\": \"https://boostbox.cloud/boost/01K9R9E2JNE1CR0ME6CFM45T8E\",\n    \"desc\": \"rss::payment::boost https://boostbox.cloud/boost/01K9R9E2JNE1CR0ME6CFM45T8E Your message here\"\n  }\n  ```\n\n- **Error Responses:**\n  - `400 Bad Request` - Invalid or missing required fields\n  - `401 Unauthorized` - Missing or invalid `X-Api-Key` header\n  - `413 Payload Too Large` - Request body exceeds `BB_MAX_BODY` limit\n\n### `GET /boost/{id}`\n\nRetrieves boostagram metadata.\n\n- **Response:** Returns an HTML page for human-readable display. The full metadata JSON is also available in the `x-rss-payment` HTTP header (URL-encoded).\n- **Status Codes:**\n  - `200 OK` - Metadata found\n  - `404 Not Found` - Unknown boost ID\n\n### `GET /health`\n\nA simple healthcheck endpoint for monitoring.\n\n- **Response:** `{\"status\": \"ok\"}`\n\n### Full API Documentation\n\nA complete OpenAPI/Swagger specification can be viewed at the `/docs` endpoint of a running instance. The raw OpenAPI JSON is available at `/openapi.json`.\n\n---\n\nBuilt with Nix and Clojure. Licensed under the MIT License.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnoblepayne%2Fboostbox","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnoblepayne%2Fboostbox","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnoblepayne%2Fboostbox/lists"}