Skip to content

Multi-account support, Forgejo provider, rename to Gitdeck#14

Merged
debba merged 9 commits into
mainfrom
feat/multi-account-provider
May 19, 2026
Merged

Multi-account support, Forgejo provider, rename to Gitdeck#14
debba merged 9 commits into
mainfrom
feat/multi-account-provider

Conversation

@debba
Copy link
Copy Markdown
Owner

@debba debba commented May 15, 2026

This is the chunk of work that turns the app from a single-account GitHub dashboard into something that can hold a few accounts at once and talk to more than just github.com. Along the way I renamed the project to Gitdeck since "GitHub Dashboard" stopped being accurate.

Heads up: it kind of works end-to-end but I'm still hitting some errors here and there — opening it now so the diff is visible and we can iron the rough edges out in follow-ups instead of in one giant branch.

What's in here

  • Provider abstraction. The GitHub-specific bits (device flow, identity fetch, owners/repos/issues/PRs/notifications, mark-read) used to live inline in dashboardData and notifications. They now sit behind a Provider interface in src/server/providers/. The core resolves the active account, asks the registry for its provider, and calls provider.listOwners / listRepos / etc. No more if (providerKind === 'github') branches in the domain layer.
  • Multi-account store. Single-account auth.json is replaced by an accountStore that supports N accounts plus ephemeral env-derived ones. First boot migrates the legacy file to accounts.json (atomic write + .legacy.bak) so existing setups keep working with zero action.
  • Account switcher. New /api/accounts endpoints (list / activate / delete) and an AccountSwitcher in the TopBar. From the dropdown you can add another GitHub account via device flow or remove an inactive one. Switching invalidates the data / notifications / CI caches.
  • Forgejo provider (Codeberg baked in). Authenticates via personal access token against /api/v1. Maps Gitea-style payloads into the same GhRepo / GhIssue / GhPullRequest / GhNotification shapes the rest of the app already speaks.
  • Capability gating. A useCapability hook reads the active account's capabilities and hides features the provider doesn't support — e.g. the Projects (kanban) tab disappears for Forgejo since it has no Projects API. Right now every GitHub account declares full capabilities so nothing changes visibly there.
  • Auth UI redesign. First-time sign-in no longer hard-starts the GitHub device flow. It loads the provider configs and shows the same picker the Add Account modal uses, so a fresh install can land directly on Codeberg via PAT without ever touching GitHub. External auth modes (gh-cli, GITHUB_TOKEN) keep their diagnostic panel.
  • Rename to Gitdeck. Title, README, i18n strings, Docker bits. Data dir migrates from ~/.gh-issues-dashboard to ~/.gitdeck on first run.

Why it's structured this way

The provider interface is the load-bearing piece. Adding a third backend (Gitea proper, GitLab, whatever) should mean writing one Provider implementation and a registry entry — no edits to dashboardData, notifications, or the React side. The capability flags are the escape hatch for "this backend doesn't have feature X" so the UI degrades gracefully instead of erroring.

The rename was deliberately bundled in: once Forgejo lands, calling the app "GitHub Dashboard" is misleading, and doing the rename separately would mean churning the same files twice.

Tests / sanity checks

  • New tests/server/accountStore.test.ts covers the migration + multi-account read/write paths.
  • I've been running it locally against both a GitHub OAuth account and a Codeberg PAT.
  • The known-rough spots: a few API error paths still leak GitHub-specific messages, and the Forgejo notification mapping is a bit lossy on edge cases. I'll chase those down in follow-up PRs once this is merged or once you've had a look.

Migration notes

  • Existing users: auth.jsonaccounts.json happens automatically on first boot; the old file is kept as auth.json.legacy.bak.
  • Existing users: ~/.gh-issues-dashboard~/.gitdeck likewise migrated on first boot.
  • No env var or Docker-flag changes are required for single-account GitHub setups.

debba and others added 9 commits May 15, 2026 09:10
Carve the GitHub-specific code (oauth device flow, identity fetch,
gh-cli loader) out into a Provider plugin and move single-account
token persistence to a new accountStore that supports N accounts plus
ephemeral env-derived ones.

On boot the store migrates a legacy auth.json into accounts.json
(atomic write + .legacy.bak) so existing users see no change. The
public surface of authProvider/oauth stays stable; tokenStore is
marked deprecated.

Behaviour for users with a single account is unchanged.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Expose GET /api/accounts, POST /api/accounts/activate and
DELETE /api/accounts so the client can list, switch and remove
stored accounts. Activate/remove invalidate the data, notifications
and CI caches.

The frontend wraps the app in an AccountProvider and renders an
AccountSwitcher in the TopBar. The switcher stays hidden until at
least two accounts exist, so users on a single account see no UI
change yet — this lays the wiring for the multi-account flow that
lands in the next step.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The TopBar switcher is now always visible. From its dropdown the user
can kick off a fresh device flow to add another GitHub account (modal
reusing /api/auth/start + /api/auth/poll), and remove any inactive
non-ephemeral account with a confirm prompt.

Adding an account triggers a context refresh; removing one invalidates
the server-side caches via DELETE /api/accounts. Switching between
accounts uses the wiring landed in the previous commit.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Add a useCapability hook that reads the active account's capabilities
exposed by /api/accounts and use it in App.tsx to hide the Projects
(kanban) tab when the provider doesn't support it. Today every account
is GitHub with full capabilities so nothing changes visibly — this
just lays the wiring so the Forgejo provider can opt out of Projects,
Dependents and Code Search without touching App.tsx again.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Add the Forgejo provider (Codeberg config baked in) that authenticates
via personal access token: fetchIdentity hits /api/v1/user with a
"token …" header, capabilities declare GraphQL/Projects/Dependents
unavailable so the UI can hide what doesn't apply.

Expose POST /api/accounts/add-token and GET /api/provider-configs.
The Add account modal becomes a two-step flow: pick a provider, then
either run the existing GitHub device flow or paste a token for
Codeberg. The new account lands in accounts.json next to any GitHub
one already configured.

Data fetching for a Forgejo-active account still falls back to the
GitHub code path (next commit re-routes it through the provider).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Move the GitHub-specific fetchers (owners, repos, issues, pull
requests, notifications, mark-read mutations) out of dashboardData
and notifications and onto GitHubProvider. ForgejoProvider implements
the same operations against /api/v1 endpoints, mapping Gitea-style
payloads into GhRepo/GhIssue/GhPullRequest/GhNotification.

The core now resolves the active account, asks the registry for its
provider, and calls provider.listOwners/listRepos/etc with no
branches on providerKind. Adding a new backend means writing a
Provider implementation and a registry entry — no edits to
dashboardData or notifications.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
AuthGate used to start the GitHub device flow immediately. Now it
loads the provider configs and shows the same picker the Add account
modal uses, so a brand-new install can land directly on Codeberg via
a personal access token without ever touching GitHub.

External auth modes (gh-cli, GITHUB_TOKEN) keep their existing
diagnostic panel.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Update AuthGate markup and styles; update app.title i18n and index.html
title
Migrate legacy ~/.gh-issues-dashboard to ~/.gitdeck and update Docker,
README, i18n, tests
@debba debba changed the title Feat/multi account provider Multi-account support, Forgejo provider, rename to Gitdeck May 15, 2026
@debba debba merged commit bb10a4f into main May 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant