mirror your GitHub repos to tangled.org automatically
TypeScript 87%
Vue 12%
CSS <1%
<1%

README.md

synchub.to #

mirror your GitHub repos to tangled.org automatically.

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+ and pnpm 10+.

Start by creating a Neon 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, 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. 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".

Keep user OAuth toggles at their defaults unless you specifically need them, but 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 create your local env file and fill all variables:

cp .env.example .env

Use these helpers for generated values:

pnpm gen:og-image-secret   # NUXT_OG_IMAGE_SECRET
pnpm gen:jwk               # NUXT_ATPROTO_PRIVATE_JWK
pnpm gen:encryption-key    # NUXT_ENCRYPTION_KEY and NUXT_SESSION_PASSWORD
pnpm gen:cron-secret       # CRON_SECRET

After .env is complete, install dependencies and run migrations:

corepack enable
pnpm install
pnpm db:migrate

Local development should run in three terminals:

# terminal 1
smee --url <your-smee-url> --target http://127.0.0.1:3000/api/github/webhook

# terminal 2
pnpm dev

# terminal 3
pnpm jobs:tick # run this to sync queued jobs while developing; Vercel Cron runs it in production

Deploy to Vercel #

synchub.to runs on Vercel with a Neon Postgres database.

  1. Apply migrations against your production database:
    NUXT_DATABASE_URL="<pooled neon connection string>" 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://<your-domain>/api/github/webhook, and set the App's Setup + Callback URLs to https://<your-domain>/connect and https://<your-domain>/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:

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.