Remote mode
Serve the editor from your deployed site so a non-technical person can edit from anywhere, with no git, no GitHub account, and no local setup. Saves become commits; your host redeploys.
What this assumes
One thing, and it's probably already set up: pushes to your branch trigger an automatic deployment (Vercel, Netlify, and friends all work this way). editsy publishes by committing to that branch, and the deploy-on-push is what takes the change live. If your host doesn't rebuild on push, publishes still land safely in git; they just won't appear on the site until your next deploy.
Set up, step by step
1. Install and scaffold.
npm install @editsy/next
npx editsy initinit creates the /editsy route, an editsy.config.ts, the next.config blocks (or prints them, if you already have a config file it won't touch), and a .env.example. It also generates a fresh EDITSY_SECRET for step 4.
2. Create a GitHub token. On GitHub: Settings, Developer settings, Fine-grained personal access tokens, Generate new token. Give it access to just your site's repo, with the Contents permission set to Read and write. Nothing else. Note the expiry date somewhere you'll see again, because publishes stop working quietly when it lapses.
3. Add editors (the next section covers the format):
npx editsy hash-password4. Set the environment variables on your host (the full list is below).
5. Check your work.
npx editsy doctorIt verifies the route, the config, the editors list, and gives the GitHub token a live test.
6. Deploy, visit yoursite.com/editsy, and log in. That's it.
Who can log in: the editors list
Editors live in EDITSY_EDITORS, a JSON array. Keep the square brackets even for one person:
[
{ "name": "Amy", "email": "amy@example.com", "passwordHash": "scrypt$..." },
{ "name": "Sam", "email": "sam@example.com" }
]Each entry needs a name and an email, plus one of:
passwordHash: whatnpx editsy hash-passwordprints. The right choice for anything deployed.password: plaintext, tolerated for quick local testing only.- neither: that person can only log in through an emailed link (needs
EDITSY_SMTP_URL).
Prefer a file over an env var? Commit an editsy.editors.json at the project root with the same array shape. Hashes are safe to commit, same idea as .htpasswd, and editsy refuses to load that file if it finds a plaintext password inside. Env and file merge, with env winning on duplicate emails.
Worth saying plainly: every editor can change what your site publishes, so treat editor passwords with the same respect as your own GitHub account. Offboarding is one edit: remove the entry (or change the password) and that person's sessions and login links stop working immediately.
Environment reference
EDITSY_SECRET: session signing secret. Long and random; changing it logs everyone out.EDITSY_EDITORS: the JSON array above (or useeditsy.editors.json).EDITSY_GITHUB_REPO:owner/repoto commit to.EDITSY_GITHUB_TOKEN: the fine-grained token from step 2.EDITSY_GITHUB_BRANCH: branch to commit to. Defaultmain.EDITSY_SMTP_URL: optional,smtps://user:pass@host; enables "email me a login link".EDITSY_EMAIL_FROM: optional sender address; defaults to the SMTP user.EDITSY_BASE_URL: your site's canonical origin, likehttps://www.example.com. Set it whenever email login is on; login links build their URLs from it instead of trusting the request's Host header.
Without auth configured, a production deployment answers 503 rather than exposing an open editor. Without the GitHub variables, saves write to the server's own disk, which on serverless hosts doesn't persist; the editor shows a warning banner when that's the case.
How publishing works
Hit Save & publish and every file you edited lands as one git commit through the GitHub API, with the editor credited in the commit message (Edited-by: name <email>). Your host's deploy-on-push does the rest.
The commit is instant; the rebuild takes a minute or two. The editor bridges that gap: after publishing it keeps showing your changes in the preview, puts up a small "your site is rebuilding" note, and lets you keep editing, so there's no flash back to the old site and no wondering whether your edits vanished.
There's no database anywhere: the repo is the content store, and sessions are stateless signed cookies.
On Vercel
Add this to next.config.ts so the editor ships with the route:
const config = {
serverExternalPackages: ["@editsy/cli"],
outputFileTracingIncludes: {
"/editsy/**": [
"./node_modules/**/@editsy/editor/dist/**",
"./node_modules/**/@editsy/editor/package.json",
],
},
};Every line matters, and each omission fails silently: serverExternalPackages keeps @editsy/cli out of the webpack bundle so it can find the editor UI at runtime; the tracing key can't contain literal [ ] (Next matches it as a picomatch glob, which treats brackets as its own syntax); and the values can't assume the editor package is hoisted to your top-level node_modules (pnpm nests it inside @editsy/cli's own install instead). The snippet above covers all three.
If something's off
First: npx editsy doctor. It checks everything below in one go, including a live test of the GitHub token.
- "The editor UI isn't built" on the deployed site: the config from the Vercel section is missing or incomplete. Add both parts and redeploy.
- 503 "editsy is disabled": production has no auth configured. Set
EDITSY_SECRETandEDITSY_EDITORS(or commiteditsy.editors.json). - 500 mentioning EDITSY_EDITORS: usually a bare
{...}instead of an array. Wrap it in[ ]. - Published, but the site never changed: check that your host actually deploys on push to that branch, and that the deployment wasn't blocked. Your edit is safe in git either way.
- "changed since you loaded it": someone (or something, like a coding agent) touched the file after you opened it. Reload the file to pick up their version; your unsaved edits to other files are unaffected.