Thanks for your interest in contributing. TSDProxy is open source because people like you are willing to pitch in, and every contribution matters. Bug reports, documentation fixes, code, and ideas are all welcome.
You will need these tools installed:
- Go 1.26 or later
- Bun (JavaScript runtime for frontend builds)
- Docker (for running containers during development)
- git
mise can manage all required tools automatically. The project includes a mise.toml that pins Go, Bun, templ, golangci-lint, gotestsum, Hugo, Vite, and Air.
# Install mise (if not already installed)
curl https://mise.run | sh
# Activate mise in your shell
eval "$(mise activate bash)" # or zsh/fish
# Install all project tools
mise installThe mise.toml also uses the fnox plugin (jdx/mise-env-fnox) for environment-specific tool configuration. mise handles this automatically on activation.
Clone the repository and run the bootstrap target to build frontend assets and generate templ templates:
git clone https://github.com/almeidapaulopt/tsdproxy.git
cd tsdproxy
make bootstrap| Target | What it does |
|---|---|
make bootstrap |
First-time setup. Builds frontend and generates templ files. |
make dev |
Starts Docker containers, frontend dev server, and hot-reload backend. |
make build |
Compiles the Go binary to ./tmp/tsdproxy. |
make test |
Runs the unit test suite. |
make test/e2e |
Runs end-to-end tests (requires Docker and a Tailscale auth key). |
make audit |
Full quality check: golangci-lint, staticcheck, go vet, deadcode, govulncheck, gosec, and tests. |
make docs |
Starts the Hugo docs site locally on port 1313. |
cmd/server/main.go Main server binary (also handles `healthcheck` subcommand)
internal/
config/ Configuration loading and file watching
core/ HTTP server, logging, health, sessions
dashboard/ SSE dashboard routes and streaming
model/ Shared types (Config, PortConfig, ProxyStatus)
proxymanager/ Central orchestrator wiring targets to proxies
proxyproviders/ Proxy provider interface and Tailscale implementation
targetproviders/ Target provider interface and Docker/List implementations
ui/ templ-generated UI components
web/ Frontend: Vite + Bun, embedded in the binary via go:embed
docs/ Hugo documentation site (separate go.mod)
e2e/ End-to-end tests (build tag: e2e)
A few conventions to follow so your changes blend with the rest of the codebase:
- SPDX headers are required on every
.gofile:This is enforced by golangci-lint. Missing headers will fail CI.// SPDX-FileCopyrightText: 2026 Paulo Almeida <almeidapaulopt@gmail.com> // SPDX-License-Identifier: MIT
- Error wrapping: use
fmt.Errorf("context: %w", err)to add context to errors. - Logging: use zerolog with structured fields:
log.With().Str("key", val).Logger(). - Follow existing patterns. When in doubt, look at how nearby code handles the same situation.
- No type suppression hacks: avoid
as anycasts or@ts-ignorecomments to silence the type checker.
- Fork the repository.
- Create a feature branch from
main. - Make your changes with clear, descriptive commit messages.
- Run
make auditlocally and fix any issues before pushing. - Open a pull request against
mainwith a description of what changed and why.
CI runs on every PR. If checks fail, push a follow-up commit to the same branch to re-trigger them.
Found a bug? Open a bug report.
For troubleshooting help, check the documentation first. Many common issues are covered there.
Have an idea? Open a feature request.
Not sure where to start? Here are some ideas:
- Bug fixes: pick an open issue tagged
bugand submit a PR. - Documentation: typos, missing examples, unclear explanations. The docs live in
docs/. - Examples: share Docker Compose configs, label setups, or deployment patterns.
- Tests: more coverage is always welcome, especially for
internal/packages. - Feature requests: describe the problem you are trying to solve, not just the solution you want.