| name | deploy |
| description | Ship a Twinfolio site live on Vercel. Use when the user says "/deploy", "put this online", "deploy to Vercel", "go live", or "set up my production env". Owns the whole path — create a GitHub repo from the local clone, push, import to Vercel, set env vars, then point at /admin → Connect GitHub for live edits. Referencing docs/deploy.md. |
| allowed-tools | Read, Bash(git:*), Bash(gh:*), Bash(vercel:*), Bash(npm:*) |
Deploy to Vercel
Get the user's Twinfolio live. Canonical reference: docs/deploy.md — Read
it first. Twinfolio is a standard Next.js app with no database; the only hard
requirement is "you can't deploy to Vercel until your code is a GitHub repo."
So the spine of this skill is: local clone → your GitHub repo → Vercel.
The site runs with zero keys (demo mode), so you can ship first and add keys
after. Never block a deploy on missing keys.
Confirm before outward actions. Creating a repo and pushing publishes code.
Before gh repo create / git push, confirm the repo name and
private/public with the user. Auth steps (gh auth login, vercel login)
are the user's to run — have them type ! gh auth login so it runs in this
session; never enter their credentials yourself.
1 · Detect the current state
git rev-parse --is-inside-work-tree 2>/dev/null
git remote -v
git status --short
gh auth status 2>&1 | head -3
Branch on what you find:
- Not a git repo (downloaded as a zip) →
git init && git add -A && git commit -m "Initial Twinfolio".
- A remote already pointing at the upstream Twinfolio (e.g.
…/twinfolio you don't own) → rename it so it isn't the push target: git remote rename origin upstream. The user's own repo becomes origin in step 2. (Keeping upstream is deliberate — it's how they pull future Twinfolio updates.)
- A remote that's already the user's repo → skip to step 3 (you're on GitHub already). This is also the state the onboarding wizard's Go-live publish leaves behind:
origin → their new repo, upstream → the original Twinfolio.
2 · Get it onto GitHub (the step people get stuck on)
The user needs their own repo. Two ways — prefer the gh CLI.
Preferred — GitHub CLI (gh)
If gh auth status shows logged in:
gh repo create <name> --private --source=. --remote=origin --push
That creates the repo in their account, wires it as origin, and pushes
main — one command. If gh isn't logged in, have them run ! gh auth login
(choose GitHub.com → HTTPS → authenticate in browser), then re-run the create.
If gh isn't installed, either install it (! brew install gh) or use the
fallback.
Fallback — no gh
- Have the user create an empty repo at https://github.com/new (no
README/.gitignore/license — the local repo already has them). Ask for the URL.
- Wire + push:
git remote add origin https://github.com/<user>/<repo>.git
git branch -M main
git push -u origin main
(If push asks for credentials, the user authenticates — don't enter their token.)
Either way, end this step with: the user's content is now a GitHub repo they own.
3 · Import to Vercel (git-connected)
Import the repo at https://vercel.com/new (not a raw CLI deploy) — importing
sets up the git connection that powers two things the user wants: every
git push auto-redeploys, and the live "Connect GitHub" editor works
(it reads VERCEL_GIT_REPO_OWNER/SLUG from that connection). Framework
auto-detects as Next.js; no build config needed.
CLI alternative: vercel link then vercel git connect to attach the repo,
then vercel --prod. The dashboard import is simpler and the default.
Set environment variables (full table in docs/deploy.md — the same checklist
the wizard's Go-live card shows). Essentials:
| Variable | Purpose |
|---|
OPENROUTER_API_KEY | Real chat brain + local-RAG embeddings — the build's npm run embed needs it at build time for citations (omit → demo mode, no index) |
ADMIN_TOKEN | Gates /admin in production. Set a long random value; the owner then opens /admin on the live site and enters it as the password. Without it, /admin is locked in prod. |
GEMINI_API_KEY | Only for the File Search backend + the voice interview (omit on the default local backend) |
GEMINI_FILE_SEARCH_STORE_NAME | File Search only, and usually unnecessary — provisioning saves the store name into twinfolio.json; this env var overrides it |
NEXT_PUBLIC_SITE_NAME / NEXT_PUBLIC_SITE_URL | Public identity (set URL to the live domain) |
USAGE_SALT | A unique value (rotates visitor quotas) |
Vercel builds + deploys on import. The user now has a live URL.
4 · Turn on live editing — Connect GitHub (no token)
This is how the owner edits the live site afterward, with no PAT and no env
vars:
- Open
/admin → Deploy tab.
- Click Connect GitHub → open
github.com/login/device, enter the shown
code, authorize. The card flips to "Connected as @you."
- From now on, saving in the Studio (identity, theme, models…) commits to the
repo and redeploys — live in ~1 minute.
owner/repo are auto-detected
from the Vercel git connection; nothing to configure.
Works because the shared "Twinfolio" OAuth App is baked in (device flow, public
client id). The token lives only in the owner's browser cookie on their own
deploy. Manual alternative: the fine-grained-PAT env vars (CONFIG_STORE=github
GITHUB_*) still work — see docs/deploy.md §5a Option B.
5 · Verify + hand off
- Open the deployment URL — chat responds (demo reply if no
OPENROUTER_API_KEY).
- Citations appear if RAG is configured (local backend:
OPENROUTER_API_KEY was
set when the build ran — if it was added after, trigger one redeploy).
/admin unlocks: open it, enter the ADMIN_TOKEN value as the password, and
Connect GitHub shows connected.
- Save something small in the Studio → confirm a commit lands on the repo and a
redeploy kicks off.
Summarize for the user: the repo, the live URL, which features are lit
(chat / RAG / connected git-admin), and that every push to main — and every
Studio save — auto-deploys.
6 · Custom domain (optional)
Vercel project → Settings → Domains → add the domain, follow the DNS records.
Once it resolves, set NEXT_PUBLIC_SITE_URL to it and redeploy so metadata and
canonical links are right. Full steps in docs/deploy.md.