GitHub Sync¶
Back up your project, track history, and collaborate via pull requests by connecting Doable to a GitHub repository.
Why connect GitHub¶
Every Doable project already has a local Git history (Versioning), but GitHub sync gives you:
- Off-site backup: your code lives on GitHub even if you delete the project in Doable.
- Full commit history: browse diffs, tag releases, and roll back from GitHub's UI.
- Team collaboration: teammates can open PRs, leave inline reviews, and merge changes outside Doable.
- CI/CD triggers: connect GitHub Actions, Vercel, Netlify, or any other pipeline to the repo.
Link your GitHub account¶
You connect GitHub once at the account level; the same token is then available to all your projects.
- Open Settings → GitHub (top-right avatar → Settings).
- Click Connect GitHub.
- You are redirected to GitHub. Review the requested scopes (Doable asks for
repoandread:user), then click Authorize. - GitHub redirects you back to Doable. Your GitHub username appears next to a green indicator.
Your token is encrypted with the instance's ENCRYPTION_KEY and stored in the database. No one, including platform admins, can read the raw token.
Note
Doable requests repo scope (full access to public and private repos) so it can create repositories and push commits on your behalf. If you only want Doable to push to public repos, you can use a fine-grained personal access token instead; paste it in the Token field of the GitHub connect dialog.
Manage multiple GitHub accounts¶
Doable stores one GitHub token per user at a time. To switch accounts:
- Open Settings → GitHub.
- Click Disconnect. This removes the stored token. Any projects still linked to repos keep their
github_repo_urlbut will need a reconnect before the next push. - Click Connect GitHub and complete OAuth with the new account.
Existing project-repo links are preserved in the database; only the auth token is removed.
Sync a project¶
First push: creating the repo¶
Open the editor for your project and click the GitHub button in the toolbar (shows a gray dot when disconnected).
Fill in the dialog:
| Field | Notes |
|---|---|
| Repository name | Auto-filled from your project name. You can change it. |
| Owner | Your GitHub username or an org you have write access to. |
| Private | On by default. Uncheck for a public repo. |
| Create new | Creates the repo on GitHub automatically if checked. Uncheck to connect to an existing repo by the same name. |
Click Connect. Doable:
- Creates the repo on GitHub (if "Create new" is checked).
- Pushes all project files as the initial commit on
main. - Stores the repo URL and marks the project as synced (green dot in toolbar).
Tip
Doable pushes over HTTPS using your stored OAuth token, with no SSH key setup required. For tighter access control (e.g. scoping push access to one repo only), create a GitHub fine-grained personal access token with Contents: Read and write on that repo and paste it into the Token field of the connect dialog.
Subsequent pushes¶
Click GitHub → Push in the toolbar (or from Project → GitHub). Enter a commit message and click Push. Doable commits the current project state and pushes to origin/main.
Pulling remote changes¶
If collaborators have pushed commits directly to GitHub, click GitHub → Pull. Doable fetches and merges the remote changes into the local project.
Conflict resolution¶
If a pull detects diverged history, Doable returns a 409 Conflict and prompts you to choose a resolution strategy:
| Strategy | Effect |
|---|---|
| Keep mine (ours) | Discards remote changes; your local state wins. |
| Use theirs | Discards local changes; GitHub's state wins. |
To abandon the merge entirely, click Abort merge. No files are changed.
For complex conflicts, resolve them in a local clone, push from there, then pull in Doable.
What's pushed¶
Doable pushes all project files: HTML, CSS, JS, images, config files, and anything else in the project directory.
What is never pushed:
- Environment variables set in Project → Settings → Environments: these stay server-side only.
- Secrets injected by the AI at runtime.
- Internal Doable metadata (
.doable/internals).
Troubleshooting¶
OAuth callback error (github_oauth_failed)
The token exchange failed. Try reconnecting. If it persists, check that your browser isn't blocking the redirect from api.doable.me.
github_invalid_state
The OAuth state parameter was lost (usually a browser extension or session issue). Try in a private/incognito window.
"No repo permission" on org repos GitHub organizations require you to grant the Doable OAuth app access in your org's Settings → Third-party Access. An org owner must approve the app, or you must use a personal access token with the required repo scope.
Token revoked / tokenExpired: true
If you revoked the token from GitHub's side (GitHub → Settings → Applications → Authorized OAuth Apps → Revoke), Doable detects the expired state on the next status check. Open Settings → GitHub and reconnect.
Push rejected, "Conflict detected" The remote has commits your local project doesn't. Pull first, resolve any conflicts, then push.