Visual UI for NextJS websites

Your Next.js site.
Edited live by your team.

Add ?edit=true to any URL. Log in with a magic link. Edit headlines, CTAs, and copy directly on the page. Vercel redeploys automatically on publish.

See detailed instructions

Scroll to reveal the demo

yoursite.com/?edit=true
EditLayerowner/editor@yoursite.com
No changes
Prism
Get a demo
✦ Prism 2.0, now in public beta
Build Something Amazing
The modern platform for teams that move fast. Launch landing pages and edit copy without waiting on engineering.
Get Started Free
Book a demo
No-code page builder
Realtime collaboration
One-click Vercel deploys
Trusted by 2,000+ product teams
Analytics overview
All pages · last 14 days
14D30D90D
12,840
Visitors
↑ 18%
3.4%
Conversion
↑ 2.1%
$9.2k
Revenue
↑ 8.4%
VisitorsLive
Recent activity
Published “Ship Marketing Copy Fast”just now
Maya edited home.hero.cta2m ago
Draft saved · pricing page14m ago
Leo edited home.feat.11h ago

Works with the stack you already use

Next.js
Vercel
GitHub
Resend
TypeScript
App Router

How it works

Up and running in minutes.

Six steps from install to live editing. No database, no third-party CMS, no pipeline changes.

01npm install @editlayer/next

Install the package

Run one command to install and scaffold. The CLI creates the API routes and config file automatically. Nothing to build from scratch.

02<EditableText id="...">

Mark editable content

Wrap any headline, paragraph, or link with EditableText. Keep your existing className and styles. EditLayer wraps around them, never rewrites them.

034 env vars

Set env vars & deploy

Add your secret, site URL, Resend API key, and GitHub token to Vercel. Push to GitHub. That's the entire backend.

04?edit=true

Open edit mode

Visit yoursite.com/?edit=true. Enter your email, click the magic link. Green outlines appear on every editable field immediately.

05git commit

Click, type, publish

Click any field to edit inline. See the live preview as you type. Save a draft to share, or hit Publish to commit directly to GitHub.

06zero infra

Vercel redeploys

Publishing writes editlayer/content.json to your repo via the GitHub API. Vercel detects the commit and redeploys automatically.

Setup guide

From zero to editable in under 5 minutes

Copy, paste, deploy. Every command and env var you need. Nothing more.

Install & initStep 1
# Inside your Next.js project
npm install @editlayer/next
npx editlayer init

# Creates editlayer.config.ts, editlayer/content.json,
# and scaffolds the API routes in app/api/editlayer/
Environment variablesStep 2
# .env.local — and add to Vercel → Settings → Environment Variables

# Generate: node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
EDITLAYER_SECRET=your-32-char-random-secret
EDITLAYER_SITE_URL=https://yoursite.com

# Magic link emails — free tier at resend.com
EDITLAYER_RESEND_API_KEY=re_xxxxxxxxxxxx
EDITLAYER_EMAIL_FROM=EditLayer <edit@yoursite.com>

# Who can log in and publish vs. draft-only
EDITLAYER_OWNERS=owner@yoursite.com
EDITLAYER_EDITORS=marketing@yoursite.com

# GitHub fine-grained token — repo contents read/write
EDITLAYER_GITHUB_TOKEN=github_pat_xxxx
EDITLAYER_GITHUB_REPO=yourname/your-repo
Option A: Paste into Cursor AI and it wires everything automaticallyRecommended

Open Cursor, start a new chat, and paste the prompt below. The agent will wrap your layout, find every hardcoded string, and convert them to <EditableText> components across your entire project.

CURSOR PROMPT
I have installed @editlayer/next (v0.3.1) in this Next.js App Router project. Your task is to complete the full integration following the exact pattern documented below. Do not deviate from these conventions.

━━ PACKAGE OVERVIEW ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

@editlayer/next is a self-hosted visual editing layer. It reads content from
editlayer/content.json at build time and writes back to it via GitHub API on publish.
There is no database, no external dashboard, and no CMS. All configuration is via
environment variables already added to .env.local and Vercel.

━━ STEP 1: ENSURE API ROUTES EXIST ━━━━━━━━━━━━━━━━━━━━

Check whether app/api/editlayer/ exists with these route files:
  login/route.ts, verify/route.ts, session/route.ts,
  logout/route.ts, publish/route.ts, drafts/route.ts

If any are missing, run: npx editlayer init
Each route file must export the corresponding handler from @editlayer/next/server:

  // app/api/editlayer/login/route.ts
  export { handleEditLayerLogin as POST } from "@editlayer/next/server"

  // app/api/editlayer/verify/route.ts
  export { handleEditLayerVerify as GET } from "@editlayer/next/server"

  // app/api/editlayer/session/route.ts
  export { handleEditLayerSession as GET } from "@editlayer/next/server"

  // app/api/editlayer/logout/route.ts
  export { handleEditLayerLogout as POST } from "@editlayer/next/server"

  // app/api/editlayer/publish/route.ts
  export { handleEditLayerPublish as POST } from "@editlayer/next/server"

  // app/api/editlayer/drafts/route.ts
  export { handleEditLayerDrafts as GET, handleEditLayerDrafts as POST } from "@editlayer/next/server"

━━ STEP 2: WRAP ROOT LAYOUT ━━━━━━━━━━━━━━━━━━━━━━━━━━━

Open app/layout.tsx. Add the provider wrapper:

  import { EditLayerProvider } from "@editlayer/next"
  import { loadEditLayerContent } from "@editlayer/next/server"

  export default async function RootLayout({ children }: { children: React.ReactNode }) {
    const content = await loadEditLayerContent()
    return (
      <html lang="en">
        <body>
          <EditLayerProvider content={content}>
            {children}
          </EditLayerProvider>
        </body>
      </html>
    )
  }

Do not remove any existing providers or imports — wrap them inside EditLayerProvider.

━━ STEP 3: MARK EDITABLE CONTENT ━━━━━━━━━━━━━━━━━━━━━━

Scan every .tsx and .jsx file in app/ and components/ for hardcoded marketing copy:
  - h1, h2, h3, h4 headings
  - p paragraph text (marketing, not UI labels)
  - Button/link labels, nav item labels, CTA text
  - Section titles, feature names, testimonial quotes
  - Footer text

Convert each to EditableText using this exact pattern:

  BEFORE: <h1 className="...">Your headline here</h1>
  AFTER:  <EditableText id="home.hero.title" as="h1" className="...">Your headline here</EditableText>

  BEFORE: <p className="...">Subheading copy</p>
  AFTER:  <EditableText id="home.hero.subtitle" as="p" className="...">Subheading copy</EditableText>

ID naming convention: "[page].[section].[field]"
  Examples: home.hero.title, home.hero.cta, pricing.header.subtitle,
            about.team.description, nav.cta.label, footer.tagline

Import at top of each file:
  import { EditableText, EditableLink } from "@editlayer/next"

For anchor tags and buttons with href:
  BEFORE: <a href="/contact" className="...">Book a call</a>
  AFTER:  <EditableLink id="home.hero.cta" href="/contact" className="...">Book a call</EditableLink>

IMPORTANT RULES:
  - Keep all existing className, style, and other props untouched
  - Only replace the text node, not the element structure
  - Do not wrap complex children (icons + text) — only wrap pure text strings
  - Do not touch code comments, console.log strings, or non-visible strings

━━ STEP 4: UPDATE content.json ━━━━━━━━━━━━━━━━━━━━━━━━

Create or update editlayer/content.json with the default value for every field you marked:

  {
    "version": 1,
    "fields": {
      "home.hero.title": "Your original headline text",
      "home.hero.subtitle": "Your original subheading text",
      ...all other fields you converted...
    },
    "meta": {
      "updatedAt": "[current ISO timestamp]",
      "updatedBy": "init",
      "commitSha": null
    }
  }

━━ DONE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

After completing all steps, tell me:
  1. How many fields were marked editable across how many files
  2. Any files you skipped and why
  3. Confirm the API routes are in place
OR DO IT MANUALLY: STEPS 3 & 4 BELOW
Wrap your root layoutStep 3
// app/layout.tsx
import { EditLayerProvider } from "@editlayer/next"
import { loadEditLayerContent } from "@editlayer/next/server"

export default async function RootLayout({ children }) {
  const content = await loadEditLayerContent()
  return (
    <html><body>
      <EditLayerProvider content={content}>
        {children}
      </EditLayerProvider>
    </body></html>
  )
}
Mark your content editableStep 4
// Any component — wrap static copy, keep everything else
import { EditableText, EditableLink } from "@editlayer/next"

export function Hero() {
  return (
    <section>
      <EditableText id="home.hero.title" as="h1">
        Your original headline
      </EditableText>

      <EditableText id="home.hero.sub" as="p">
        Your original subheadline
      </EditableText>

      <EditableLink id="home.hero.cta" href="/contact">
        Book a call
      </EditableLink>
    </section>
  )
}
Deploy, then editStep 5
# Push to GitHub — Vercel deploys automatically
git add .
git commit -m "Add EditLayer"
git push

# Then visit your live site with ?edit=true
# → Enter your owner email
# → Click the magic link in your inbox
# → Green outlines appear on every editable field
# → Click any field, edit, Save Draft or Publish
# → Publish commits content.json → Vercel redeploys

What you get

Everything you need. Nothing you don't.

Built for developers who want to hand editing control to their clients, without handing over their codebase.

Magic link auth

Email-only login with short-lived signed tokens. No passwords, no OAuth config. HTTP-only cookies for sessions.

In-page editing

Green outlines on hover. Click to open an inline editor. Live preview of changes before publishing.

GitHub → Vercel

Publishing commits content.json to your repo. Vercel detects the push and redeploys. Zero extra infra.

Roles & access

Owners publish. Editors save drafts. Add team members via env vars. No database required.

Secure by default

Origin validation, rate limiting, field ID allowlists, content sanitization. Plain text only, no arbitrary HTML.

Zero dependencies

No CMS subscription. No hosted service. No vendor lock-in. Just an npm package and your existing Vercel project.

FAQ

Frequently asked questions

Everything you need to know before installing.

Start today

One command away from a
live editor.

Your marketing team won't need to open a code editor just to change a headline. Give them the power to edit, safely.

Read the setup guidenpm install @editlayer/next
v0.3.1·TypeScript·Next.js App Router