{"id":50655296,"url":"https://github.com/taurusxin/speedtest-next","last_synced_at":"2026-06-07T23:30:39.626Z","repository":{"id":346325902,"uuid":"1189397280","full_name":"taurusxin/speedtest-next","owner":"taurusxin","description":"🌐 Open-source, self-hosted alternative to librespeed with native IPv4/IPv6 dual-stack switching.","archived":false,"fork":false,"pushed_at":"2026-03-23T12:15:02.000Z","size":3162,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-07T07:05:12.005Z","etag":null,"topics":["golang","librespeed","react","speedtest","typescript"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","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/taurusxin.png","metadata":{"files":{"readme":"README.en.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":"2026-03-23T09:28:40.000Z","updated_at":"2026-03-23T12:13:53.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/taurusxin/speedtest-next","commit_stats":null,"previous_names":["taurusxin/speedtest-next"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/taurusxin/speedtest-next","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/taurusxin%2Fspeedtest-next","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/taurusxin%2Fspeedtest-next/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/taurusxin%2Fspeedtest-next/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/taurusxin%2Fspeedtest-next/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/taurusxin","download_url":"https://codeload.github.com/taurusxin/speedtest-next/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/taurusxin%2Fspeedtest-next/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34042554,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-07T02:00:07.652Z","response_time":124,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":["golang","librespeed","react","speedtest","typescript"],"created_at":"2026-06-07T23:30:37.874Z","updated_at":"2026-06-07T23:30:39.618Z","avatar_url":"https://github.com/taurusxin.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Speedtest Next\n\n[简体中文](./README.md) | English\n\n[![Docker](https://img.shields.io/badge/Docker-ready-2496ED?style=for-the-badge\u0026logo=docker\u0026logoColor=white)](https://hub.docker.com/r/taurusxin/speedtest-next)\n[![License](https://img.shields.io/github/license/taurusxin/speedtest-next?style=for-the-badge\u0026logo=opensourceinitiative\u0026logoColor=white\u0026color=3DA639)](https://github.com/taurusxin/speedtest-next/blob/main/LICENSE)\n[![Release](https://img.shields.io/github/v/release/taurusxin/speedtest-next?style=for-the-badge\u0026logo=github\u0026logoColor=white\u0026color=181717)](https://github.com/taurusxin/speedtest-next/releases)\n[![Stars](https://img.shields.io/github/stars/taurusxin/speedtest-next?style=for-the-badge\u0026logo=github\u0026logoColor=white\u0026color=181717)](https://github.com/taurusxin/speedtest-next/stargazers)\n\nA self-hosted network speed test platform powered by Go and React. It features IPv4/IPv6 dual-stack testing, latency and jitter measurement, download/upload throughput testing, and real-time front-end charting.\n\n![Speedtest Next Demo](./assets/demo.png)\n\n## Features\n\n- A single Go service serving both the speed test API and front-end static assets\n- React + Mantine front-end with automatic dark/light mode detection\n- IPv4 / IPv6 dual-stack testing switching\n- Phased testing: latency, jitter, download, and upload\n- Distinct chart visualizations for download and upload phases\n- Front-end assets embedded in the Go binary for effortless deployment\n- Dynamic configuration of target URLs and test parameters via runtime environment variables\n\n## Deployment\n\n### Method 1: Docker Compose\n\nIdeal for deploying directly using the automated images on Docker Hub. Please refer to the [Compose configuration](./deploy/docker/compose.yaml).\n\n1. Copy the environment variables template:\n\n```bash\ncp .env.example .env\n```\n\n2. Edit `.env` and fill in at least the following variables:\n\n```bash\nSPEEDTEST_TARGET_IPV4=speedtest-v4only.example.com\nSPEEDTEST_TARGET_IPV6=speedtest-v6only.example.com\n```\n\nIf you wish to deploy a specific version, you can set:\n\n```bash\nIMAGE_TAG=v1.0.0\n```\n\nBy default, it uses:\n\n```bash\nIMAGE_TAG=latest\n```\n\n3. Start the service:\n\n```bash\ndocker compose up -d\n```\n\n4. View the logs:\n\n```bash\ndocker compose logs -f\n```\n\n5. Stop the service:\n\n```bash\ndocker compose down\n```\n\nRelated files:\n\n- Compose File: [compose.yaml](./compose.yaml)\n- Environment Variables Template: [.env.example](./.env.example)\n\n### Method 2: systemd Daemon\n\nIdeal for running the pre-compiled binary from GitHub Releases on your server, managed by systemd.\n\n1. Download and extract the binary package for your platform from GitHub Releases.\n2. Upload it to your server, for example:\n\n```bash\nsudo mkdir -p /opt/speedtest-next\nsudo cp speedtest-next /opt/speedtest-next/\nsudo chmod +x /opt/speedtest-next/speedtest-next\n```\n\n3. Prepare the environment variables file:\n\n```bash\nsudo mkdir -p /etc/speedtest-next\nsudo cp deploy/systemd/speedtest-next.env.example /etc/speedtest-next/speedtest-next.env\nsudo nano /etc/speedtest-next/speedtest-next.env\n```\n\nFill in at least the following:\n\n```bash\nSPEEDTEST_TARGET_IPV4=speedtest-v4only.example.com\nSPEEDTEST_TARGET_IPV6=speedtest-v6only.example.com\n```\n\n4. Install and start the service:\n\n```bash\nsudo cp deploy/systemd/speedtest-next.service /etc/systemd/system/speedtest-next.service\nsudo systemctl daemon-reload\nsudo systemctl enable --now speedtest-next\n```\n\n5. Check the status:\n\n```bash\nsudo systemctl status speedtest-next\nsudo journalctl -u speedtest-next -f\n```\n\nRelated files:\n\n- Service File: [deploy/systemd/speedtest-next.service](./deploy/systemd/speedtest-next.service)\n- Environment Variables Template: [deploy/systemd/speedtest-next.env.example](./deploy/systemd/speedtest-next.env.example)\n\n### Nginx Reverse Proxy and CORS\n\nThe Speedtest Next backend service automatically handles Cross-Origin Resource Sharing (CORS) requests and sends the appropriate CORS response headers. If you use Nginx as a reverse proxy, you need to configure `proxy_pass_header Server;` to ensure that the CORS headers provided by the backend are not discarded by Nginx.\n\nReference configuration:\n\n```nginx\nserver {\n    listen 80;\n    server_name speedtest.example.com;\n\n    location / {\n        proxy_pass http://127.0.0.1:8080;\n        proxy_set_header Host $host;\n        proxy_set_header X-Real-IP $remote_addr;\n        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n        proxy_set_header X-Forwarded-Proto $scheme;\n        \n        # Required: Preserve headers set by the backend service (prevents CORS headers from being lost)\n        proxy_pass_header Server;\n    }\n}\n```\n\n## Runtime Environment Variables\n\nThe following environment variables are supported:\n\n| Variable | Required | Default | Description |\n| --- | --- | --- | --- |\n| `SPEEDTEST_TARGET_IPV4` | Yes | - | IPv4 target domain or full URL |\n| `SPEEDTEST_TARGET_IPV6` | Yes | - | IPv6 target domain or full URL |\n| `SPEEDTEST_ADDR` | No | `:8080` | Service listening address |\n| `SPEEDTEST_STATIC_DIR` | No | - | Custom external static directory; overrides embedded assets if set |\n| `SPEEDTEST_LOG_NOISY_API` | No | `false` | Enable access logs for high-frequency test APIs |\n| `SPEEDTEST_ALLOWED_ORIGINS` | No | Empty | Comma-separated CORS whitelist; echoes the request `Origin` dynamically if empty |\n| `SPEEDTEST_SITE_TITLE` | No | `SpeedTest Next` | Main page title and browser tab title |\n| `SPEEDTEST_GITHUB_URL` | No | Repository URL | GitHub link in the top right corner of the page |\n| `SPEEDTEST_LATENCY_SAMPLE_COUNT` | No | `10` | Latency test sample count; higher values yield more stable results but take longer |\n| `SPEEDTEST_LATENCY_SAMPLE_GAP_MS` | No | `160` | Latency sampling gap (ms); higher values provide better jitter observation |\n| `SPEEDTEST_DOWNLOAD_CONCURRENCY` | No | `6` | Download test concurrent threads; higher values saturate bandwidth more easily |\n| `SPEEDTEST_DOWNLOAD_DURATION_MS` | No | `9000` | Download test duration (ms) |\n| `SPEEDTEST_DOWNLOAD_CHUNK_BYTES` | No | `6291456` | Single download chunk size (approx. 6 MiB) |\n| `SPEEDTEST_UPLOAD_CONCURRENCY` | No | `4` | Upload test concurrent threads |\n| `SPEEDTEST_UPLOAD_DURATION_MS` | No | `7000` | Upload test duration (ms) |\n| `SPEEDTEST_UPLOAD_CHUNK_BYTES` | No | `1048576` | Single upload chunk size (approx. 1 MiB) |\n| `SPEEDTEST_SAMPLING_INTERVAL_MS` | No | `250` | Real-time speed sampling interval on the front-end (ms) |\n| `SPEEDTEST_CHART_POINTS_LIMIT` | No | `120` | Maximum number of sample points for the chart |\n| `SPEEDTEST_DISPLAY_SMOOTHING_FACTOR` | No | `0.35` | Display smoothing factor; larger values are more real-time, smaller values are smoother |\n\nNotes:\n\n- The service will fail to start if both `SPEEDTEST_TARGET_IPV4` and `SPEEDTEST_TARGET_IPV6` are missing.\n- All other test parameters are optional and will fallback to built-in defaults if omitted.\n- The front-end fetches these configurations from the `/api/v1/runtime-config` endpoint on startup, ensuring they take effect dynamically at runtime even though the front-end is static.\n\n## Development and Building\n\nPlease refer to the [Development Guide](./DEVELOPMENT.md) to learn how to develop and build the project locally.\n\n## Project Structure\n\n```text\n.\n├── .github/workflows/release.yml   # Automated release via GitHub Actions\n├── main.go                         # Go service entrypoint, speed test API, static assets, CORS, and logging\n├── main_test.go                    # Go service basic tests\n├── Dockerfile                      # Docker multi-stage build\n├── DEVELOPMENT.md                  # Development and building guide\n├── deploy/                         # Deployment configurations\n│   ├── docker/                     # Docker Compose configuration\n│   │   └── compose.yaml\n│   └── systemd/                    # systemd service configuration\n├── web/                            # React front-end\n│   ├── src/\n│   │   ├── App.tsx                 # Page components and interactions\n│   │   ├── App.css                 # Page styles\n│   │   ├── config.ts               # Default configs and runtime config loading\n│   │   ├── main.tsx                # Mantine theme and front-end entrypoint\n│   │   ├── speedtest.ts            # Front-end speed testing logic\n│   │   └── index.css               # Global styles and dark/light mode variables\n│   └── package.json\n└── docs/ARCHITECTURE.md            # Architecture and testing logic documentation\n```\n\n## Notes\n\n- Browsers cannot strictly force IPv4 or IPv6 under the same hostname, so dual-stack switching relies on different target domains.\n- Curves and instantaneous speeds utilize presentation-layer smoothing, while final speed test results are still calculated based on cumulative bytes and total duration.\n- The page title, GitHub link, test targets, and test parameters can all be configured dynamically via runtime environment variables.\n\nFor a more detailed explanation of the architecture and request flows, please see [docs/ARCHITECTURE.md](./docs/ARCHITECTURE.md).","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftaurusxin%2Fspeedtest-next","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftaurusxin%2Fspeedtest-next","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftaurusxin%2Fspeedtest-next/lists"}