What it does
After a run, the workspace exposes a Publish to GitHub button next to Figma Ready Assets. Connect your GitHub account once via OAuth, then commit a Claude-Skill-shaped folder to any repo you can push to.
The published folder has this shape:
{folder}/
DESIGN.md # canonical nine-section design spec
SKILL.md # Claude Skill manifest (frontmatter)
README.md # repo intro and quick-start
tokens.css # :root { --primary: ...; --ring: ...; } in HSL triples
fonts.css # Google Font @import + family aliases
tailwind.preset.js # tailwind preset wiring hsl(var(--token))
tokens/colors.json
tokens/typography.json
tokens/spacing.json
Folder defaults to design-systems/{brand-slug} so a single repo can hold many brands. You can override the folder, branch, and commit message at publish time.
How it works (OAuth)
This product uses GitHub OAuth — there are no Personal Access Tokens to copy or store.
- Generate a DESIGN.md from any source.
- In the Results card, click Publish to GitHub to open the form.
- Click Connect GitHub. You will be sent to github.com/login/oauth/authorize, which asks you to grant the app
reposcope. - After approving, GitHub redirects you back to the workspace and the form unlocks. The connected GitHub user is shown with their avatar and login.
- Enter
owner/repoand (optionally) override branch / folder / commit message. - Click Push commit. A single atomic commit is created via the GitHub Git Data API.
- On success, the form shows a View commit link.
Why repo scope
The OAuth app requests the repo scope so you can publish to both public and private repos. If you only ever publish to public repos and want to scope down later, you can revoke the install at any time and re-grant a narrower scope at the GitHub end.
Where the token lives
- The OAuth access token is encrypted with AES-GCM using a server-side secret and stored in an
httpOnly,secure,SameSite=Laxcookie calledgh_token. It is never exposed to client-side JavaScript and never persisted to a database. - The cookie has a 30-day max age. Disconnect at any time to delete it.
- The token is forwarded to api.github.com only when you click Push commit (or when the workspace fetches
/api/github/meto check connection state).
Disconnecting and revoking
- In the workspace: open the publish form, click Disconnect in the connected-account chip. This calls
/api/github/oauth/disconnectto delete the cookie immediately. - On GitHub: visit github.com/settings/applications, find this app, and click Revoke. Revoking on GitHub also invalidates the cookie on the next API call.
Self-hosting setup
If you are running the app yourself, register a GitHub OAuth App and set the following environment variables:
GITHUB_OAUTH_CLIENT_ID— from your GitHub OAuth App.GITHUB_OAUTH_CLIENT_SECRET— from your GitHub OAuth App. Treat as secret.GITHUB_OAUTH_REDIRECT_URL— optional. Defaults to${origin}/api/github/oauth/callback. Match this in the GitHub OAuth App settings.GITHUB_OAUTH_COOKIE_SECRET— 32+ byte random string used to derive an AES-GCM key for the cookie. Generate one withopenssl rand -base64 48.
Registering the OAuth App on GitHub
- Go to github.com/settings/developers → OAuth Apps → New OAuth App.
- Application name: anything (e.g. "Fiction Tribe DesignSpec").
- Homepage URL: your deployed origin (e.g.
https://your-domain.com). - Authorization callback URL:
https://your-domain.com/api/github/oauth/callback. - Click Register application, copy the Client ID, generate a Client Secret, and copy that.
For local dev, register a separate OAuth App with http://localhost:3000 and http://localhost:3000/api/github/oauth/callback.
How Claude Skills consume this
Point Claude (or any LLM rendering pipeline) at the published folder and it will read:
SKILL.mdfor skill metadata and capability description.DESIGN.mdfor the full nine-section brand spec, including the renderer-ready Token Map and Implementation Warnings in Section 9.tokens.cssfor the canonical:rootHSL triples.tailwind.preset.jswhen generating shadcn/Tailwind components.
Updating the brand later is just another Publish to GitHub click — re-run the source through the generator and the commit becomes a clean diff of the brand evolution.
Common errors
Connect failed
The redirect URL does not match the OAuth App configuration, or the env vars are missing/typoed. Check GITHUB_OAUTH_REDIRECT_URL against the value registered on GitHub.
401 from GitHub on publish
Your OAuth session expired or was revoked. Click Disconnect in the form (if visible) and reconnect.
403 from GitHub
The OAuth grant did not include repo scope, or the repo is in an org that has restricted third-party OAuth apps. Contact the org owner or reconnect and approve the scope.
404 from GitHub
The owner, repo, or branch does not exist, or your GitHub account does not have access. Confirm owner/repo and that the branch exists.
422 from GitHub
The repo may be empty (no first commit yet) or the branch is protected. Push an initial commit to the branch from a workstation, or unprotect the branch temporarily.