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
- GitHub App "dotUI" + one server function for code→token exchange.
- "Save to GitHub" creates/updates the user's
dotui-presets repo: a shadcn registry.json with one item per preset.
- 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.
- 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.
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)
client_secretand 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.public_reposcope grants write to ALL public repos. A GitHub App installed on a single repo (which the app creates, e.g.dotui-presets) withcontents: writegives the least-scary consent screen. Note: App user tokens expire in 8h by default (configurable); plan refresh or disable expiration.registry.jsonat repo root →npx shadcn@latest add <user>/<repo>/<item>, with#refSHA pinning. No raw URLs needed. Public repos only.api.github.comhas full CORS (create repo, commit files, 5k req/h per user).Proposed shape
dotui-presetsrepo: a shadcnregistry.jsonwith one item per preset.dotui.org/r/*?preset=…— trivial, but installs depend on dotui.org./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.
Known trade-offs
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.