{"id":51123654,"url":"https://github.com/rishavnandi/tsdeck","last_synced_at":"2026-06-25T05:30:44.146Z","repository":{"id":361257105,"uuid":"1253757409","full_name":"rishavnandi/tsdeck","owner":"rishavnandi","description":null,"archived":false,"fork":false,"pushed_at":"2026-05-29T21:16:45.000Z","size":214,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-29T21:16:49.065Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"wtfpl","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rishavnandi.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":"2026-05-29T19:33:27.000Z","updated_at":"2026-05-29T21:07:46.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/rishavnandi/tsdeck","commit_stats":null,"previous_names":["rishavnandi/tsdeck"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/rishavnandi/tsdeck","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rishavnandi%2Ftsdeck","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rishavnandi%2Ftsdeck/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rishavnandi%2Ftsdeck/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rishavnandi%2Ftsdeck/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rishavnandi","download_url":"https://codeload.github.com/rishavnandi/tsdeck/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rishavnandi%2Ftsdeck/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34761844,"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-25T02:00:05.521Z","response_time":101,"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":[],"created_at":"2026-06-25T05:30:43.427Z","updated_at":"2026-06-25T05:30:44.136Z","avatar_url":"https://github.com/rishavnandi.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# TSDeck\n\n**Ninite for Homelabbers**\n\nPick your self-hosted apps from a catalog, get a one-line `curl` command, and run it on your server. Docker is installed if missing, your apps are exposed on your Tailscale network with automatic HTTPS via TSDProxy, and your data persists across re-runs.\n\n## How it works\n\n1. **Browse** the app catalog at [tsdeck.rishavnandi.workers.dev](https://tsdeck.rishavnandi.workers.dev)\n2. **Select** the apps you want\n3. **Copy** the generated `curl` command\n4. **Run** it on your Linux server\n5. **Access** your apps at `https://app-name.your-tailnet.ts.net`\n\nThe webapp never stores your credentials or connects to your servers. All secrets are prompted at runtime on your own hardware.\n\n## Architecture\n\n```\nUser browser:\n  ┌─────────────┐     POST /generate      ┌──────────────┐\n  │   Frontend  │ ──────────────────────► │  Hono Worker │\n  │(Cloudflare  │                         │(Cloudflare    │\n  │   Pages)    │ ◄──── slug + url ────── │   Workers)    │\n  └─────────────┘                         └──────────────┘\n                                                 │\n                                                 ▼\n                                          ┌──────────────┐\n                                          │ Cloudflare KV│\n                                          │  (15-min TTL)│\n                                          └──────────────┘\n\nUser server:\n  curl -fsSL https://tsdeck.rishavnandi.workers.dev/s/abc123 | bash\n       │\n       ▼\n  ┌──────────────┐\n  │ Bootstrap    │──► Install Docker (if missing)\n  │ Script       │──► Prompt for Tailscale Auth Key\n  │              │──► Prompt for app env vars\n  │              │──► Fetch compose templates from GitHub\n  │              │──► Assemble docker-compose.yml\n  │              │──► Start containers (incl. TSDProxy)\n  └──────────────┘\n```\n\n## Project Structure\n\n```\ntsdeck/\n├── apps/                    # App templates (compose.yaml + meta.yaml)\n│   ├── jellyfin/\n│   ├── immich/\n│   ├── sonarr/\n│   ├── radarr/\n│   ├── prowlarr/\n│   ├── bazarr/\n│   ├── qbittorrent/\n│   ├── vaultwarden/\n│   ├── portainer/\n│   └── jellyseerr/\n├── frontend/               # Static HTML/JS site (Cloudflare Pages)\n│   ├── index.html\n│   ├── app.js\n│   └── styles.css\n├── api/                    # Hono API (Cloudflare Workers)\n│   ├── src/\n│   │   ├── index.ts        # API routes\n│   │   ├── generator.ts    # Bash script generator\n│   │   └── apps.ts         # App metadata\n│   ├── test/\n│   ├── wrangler.toml\n│   └── package.json\n├── scripts/\n│   └── validate-apps.js    # CI check for app templates\n└── package.json\n```\n\n## Development\n\n### Prerequisites\n\n- [Bun](https://bun.sh)\n\n### Setup\n\n```bash\n# Install dependencies\ncd api \u0026\u0026 bun install\n\n# Run API locally\nbun run dev\n\n# Run tests\nbun test\n\n# Validate app templates\nbun run validate-apps\n```\n\n### Deploy\n\nTSDeck uses Cloudflare Workers **Static Assets** — the frontend and API are deployed together as a single Worker.\n\n```bash\ncd api \u0026\u0026 bunx wrangler deploy\n```\n\nDeployed at `https://tsdeck.rishavnandi.workers.dev`\n\n- `https://tsdeck.rishavnandi.workers.dev/` — Frontend (catalog UI)\n- `https://tsdeck.rishavnandi.workers.dev/apps` — API (app catalog JSON)\n- `https://tsdeck.rishavnandi.workers.dev/generate` — API (generate slug)\n- `https://tsdeck.rishavnandi.workers.dev/s/:slug` — API (serve bootstrap script)\n\n## Contributing Apps\n\n1. Create `apps/\u003capp-id\u003e/compose.yaml` and `apps/\u003capp-id\u003e/meta.yaml`\n2. Follow the schema in `apps/README.md`\n3. Add the app to `apps/manifest.json` and `api/src/apps.ts`\n4. Run `bun run validate-apps`\n5. Open a pull request\n\n## Security\n\n- **Zero server-side secrets**: The webapp never collects Tailscale auth keys, passwords, or server credentials.\n- **Ephemeral slugs**: Setup commands expire after 15 minutes.\n- **Inspectable scripts**: Every generated script is plain bash. Read it before piping to `bash`.\n- **Dry-run mode**: Set `DRY_RUN=1` before running the script to preview changes.\n\n## License\n\nWTFPL","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frishavnandi%2Ftsdeck","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frishavnandi%2Ftsdeck","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frishavnandi%2Ftsdeck/lists"}