Skip to content

User presets saved to their own GitHub as shadcn registries (no database) #503

Description

@mehdibha

Durable user presets without running a database: users sign in with GitHub and their presets live as a shadcn-compatible registry in a repo they own. Builds on the local "My presets" tier (named localStorage saves).

Verified constraints (researched July 2026)

  • Pure client-side GitHub OAuth is not possible. The token exchange still requires client_secret and the token/device endpoints have no CORS (GitHub's announced SPA support has not shipped — see github.com/orgs/community/discussions/15752). The standard minimal pattern (Decap CMS, giscus): one serverless token-exchange function — a TanStack Start server function on Vercel with the secret in an env var. No database anywhere; the token lives client-side.
  • Use a GitHub App, not a classic OAuth app. Classic public_repo scope grants write to ALL public repos. A GitHub App installed on a single repo (which the app creates, e.g. dotui-presets) with contents: write gives the least-scary consent screen. Note: App user tokens expire in 8h by default (configurable); plan refresh or disable expiration.
  • Skip gists: GitHub App tokens 403 on gist endpoints; gists would force classic OAuth.
  • shadcn CLI has native GitHub registry support: registry.json at repo root → npx shadcn@latest add <user>/<repo>/<item>, with #ref SHA pinning. No raw URLs needed. Public repos only.
  • Everything post-auth runs in the browser: api.github.com has full CORS (create repo, commit files, 5k req/h per user).

Proposed shape

  1. GitHub App "dotUI" + one server function for code→token exchange.
  2. "Save to GitHub" creates/updates the user's dotui-presets repo: a shadcn registry.json with one item per preset.
  3. Two content options, start with (a):
    • (a) Pointer: store the encoded preset state + items pointing at dotui.org/r/*?preset=… — trivial, but installs depend on dotui.org.
    • (b) Baked: at save time, fetch the fully-published output from /r/* and commit real files — self-contained, "code you own", the compelling end state.
      Always store the encoded config alongside so "edit in dotUI" round-trips.
  4. The builder's preset gallery lists the user's GitHub presets next to built-ins and local saves, behind the same store interface as "My presets".

Known trade-offs

  • No GitHub account → local saves + share links only (acceptable: install path already assumes a dev).
  • Private preset repos are second-class (shadcn GitHub addressing is public-only; auth-header registries exist but clunky).
  • No central community browsing without a central index; a later no-DB option is GitHub topic search (dotui-preset).

Timing

The /create builder has a planned experience-spec-first rewrite; the App + server function + repo format are rewrite-proof, but the save/load UI should be specced as part of that rewrite rather than bolted onto the current builder.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions