# synchub.to > mirror your GitHub repos to [tangled.org](https://tangled.org) automatically. - [👉  Check it out](https://synchub.to/) Install the GitHub App, connect your tangled identity, and every commit, branch, and tag will be mirrored to tangled. ## Features - no workflow file required - one-time OAuth connection to tangled - per-push sync of branches and tags - a dashboard where you can resync, pause, or rotate keys > [!IMPORTANT] > Only public repositories are synced (tangled does not yet support private repositories). ## Run it locally You will need [Node 24+](https://nodejs.org) and [pnpm 10+](https://pnpm.io). Start by creating a [Neon](https://neon.tech) project, then copy the pooled Postgres connection string from the Neon dashboard. Keep it ready for the `NUXT_DATABASE_URL` value in the env setup step below. Next, open [smee.io](https://smee.io), create a new channel, and copy that URL. This URL is the webhook destination GitHub should send to during local development. If you do not have the CLI yet, install it with `pnpm add -g smee-client`. Then create a new GitHub App at [github.com/settings/apps/new](https://github.com/settings/apps/new). On the creation form, set GitHub App name to any unique name, Homepage URL to your local origin (`http://127.0.0.1:3000`), Callback URL to `http://127.0.0.1:3000/api/github/oauth/callback`, Setup URL to `http://127.0.0.1:3000/connect`, and enable "Redirect on update". Leave the user authorization toggles at their defaults, but do copy the Client ID and generate a client secret: the Callback URL above drives a user-OAuth leg that proves a connecting user administers the installation before any tangled handle is bound to it, so `NUXT_GITHUB_APP_CLIENT_ID` and `NUXT_GITHUB_APP_CLIENT_SECRET` are required, not optional. Keep webhooks active and set Webhook URL to your Smee URL with a webhook secret you choose. Set repository permissions to `contents:read` and `metadata:read`. For event subscriptions, use `push`, `create`, `delete`, and `repository`. If you do not see those event checkboxes yet, save the app after adding the webhook URL, then return to the "Permissions & events" page and select them there. After creation, copy App ID, Client ID, generate a client secret, and generate a private key (`.pem`) for the `NUXT_GITHUB_APP_*` values. If you need to install this app in organizations/accounts other than the owner account, go to Advanced > Danger zone and make the app public. Now install dependencies, which the secret-generation helpers below need: ```bash corepack enable pnpm install ``` Create your local env file and fill in every variable: ```bash cp .env.example .env ``` Use these helpers for the generated values: ```bash pnpm gen:jwk # NUXT_ATPROTO_PRIVATE_JWK pnpm gen:encryption-key # NUXT_ENCRYPTION_KEY and NUXT_SESSION_PASSWORD pnpm gen:cron-secret # CRON_SECRET ``` Once `.env` is complete, apply migrations: ```bash pnpm db:migrate ``` Local development runs in three terminals. Proxy webhooks to your dev server: ```bash smee --url --target http://127.0.0.1:3000/api/github/webhook ``` Run the app: ```bash pnpm dev ``` And drain the job queue as needed while developing (Vercel Cron does this in production): ```bash pnpm jobs:tick ``` ## Deploy to Vercel synchub.to runs on Vercel with a Neon Postgres database. 1. Apply migrations against your production database: ```bash NUXT_DATABASE_URL="" pnpm db:migrate ``` 2. Import the repo into Vercel (the Nuxt preset is auto-detected) and set every variable from `.env.example` under **Settings > Environment Variables**. Mark the secrets (`NUXT_DATABASE_URL`, `NUXT_GITHUB_APP_PRIVATE_KEY`, `NUXT_GITHUB_APP_CLIENT_SECRET`, `NUXT_ATPROTO_PRIVATE_JWK`, `NUXT_ENCRYPTION_KEY`, `NUXT_SESSION_PASSWORD`, `NUXT_GITHUB_WEBHOOK_SECRET`, `CRON_SECRET`) as **Sensitive**. 3. Set `NUXT_PUBLIC_URL` to your real origin, point the GitHub App webhook at `https:///api/github/webhook`, and set the App's Setup + Callback URLs to `https:///connect` and `https:///api/github/oauth/callback`. 4. Deploy. The worker runs on a Vercel Cron (declared in `nuxt.config.ts`, so no `vercel.json` is needed) and appears under **Settings > Cron Jobs** after the first deploy. > [!NOTE] > The GitHub App private key is multi-line, but Vercel env values are single > line. Collapse the newlines to literal `\n` before pasting: > > ```bash > awk 'NF {printf "%s\\n", $0}' your-app.private-key.pem > ``` > > Locally, keep the real newlines as shown in `.env.example`. Migrations are > manual: re-run `pnpm db:migrate` against production whenever you ship a > schema change. ## License Made with ❤️ Published under [MIT License](./LICENCE).