next-content-overlay 0.1.0 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +164 -42
- package/dist/{index.js → cli/index.js} +344 -53
- package/dist/react/index.d.ts +73 -0
- package/dist/react/index.js +963 -0
- package/dist/server/index.d.ts +104 -0
- package/dist/server/index.js +445 -0
- package/package.json +28 -5
- package/dist/index.cjs +0 -555
- package/dist/index.d.cts +0 -1
- /package/dist/{index.d.ts → cli/index.d.ts} +0 -0
package/README.md
CHANGED
|
@@ -1,65 +1,193 @@
|
|
|
1
1
|
# next-content-overlay
|
|
2
2
|
|
|
3
|
-
**
|
|
3
|
+
**Plug-and-play inline CMS for Next.js — click text on the page, edit it, publish. No database.**
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
`next-content-overlay` gives any Next.js App Router project a Squarespace-style inline editor in three files. Your content lives in a plain JSON file in your repo. Version control handles history. There is no CMS platform, no vendor lock-in, no config hell.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
It started as a CLI-only tool in v0.1 (`init → scan → edit → publish`). As of **v1.0** the primary interface is a React component + server bundle that you drop into a layout — and the CLI is still there as a secondary workflow when you'd rather edit copy from the terminal.
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
> **From v0.1 → v1.0:** the CLI still ships and still works. The big upgrade is that you can now edit text visually, on the page, with drafts and version history, without leaving the browser. See [CHANGELOG.md](CHANGELOG.md) for the full migration guide.
|
|
10
10
|
|
|
11
|
+
## Install
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npm i -D next-content-overlay
|
|
11
15
|
```
|
|
12
|
-
|
|
16
|
+
|
|
17
|
+
## Quickstart (visual editor — 3 files)
|
|
18
|
+
|
|
19
|
+
### 1. Wrap your root layout
|
|
20
|
+
|
|
21
|
+
```tsx
|
|
22
|
+
// app/layout.tsx
|
|
23
|
+
import { ContentOverlayProvider, EditModeToggle } from "next-content-overlay";
|
|
24
|
+
import { getContent } from "next-content-overlay/server";
|
|
25
|
+
|
|
26
|
+
export default async function RootLayout({ children }: { children: React.ReactNode }) {
|
|
27
|
+
const content = await getContent();
|
|
28
|
+
return (
|
|
29
|
+
<html>
|
|
30
|
+
<body>
|
|
31
|
+
<ContentOverlayProvider initialContent={content}>
|
|
32
|
+
{children}
|
|
33
|
+
<EditModeToggle />
|
|
34
|
+
</ContentOverlayProvider>
|
|
35
|
+
</body>
|
|
36
|
+
</html>
|
|
37
|
+
);
|
|
38
|
+
}
|
|
13
39
|
```
|
|
14
40
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
41
|
+
### 2. Wrap any text in `<Editable>`
|
|
42
|
+
|
|
43
|
+
```tsx
|
|
44
|
+
// app/page.tsx
|
|
45
|
+
import { Editable } from "next-content-overlay";
|
|
46
|
+
|
|
47
|
+
export default function Page() {
|
|
48
|
+
return (
|
|
49
|
+
<main>
|
|
50
|
+
<Editable k="hero.title" as="h1">Welcome to my site</Editable>
|
|
51
|
+
<Editable k="hero.subtitle" as="p" multiline>
|
|
52
|
+
Build something amazing with zero config.
|
|
53
|
+
</Editable>
|
|
54
|
+
</main>
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
```
|
|
18
58
|
|
|
19
|
-
|
|
59
|
+
### 3. Mount the API handler
|
|
20
60
|
|
|
21
|
-
|
|
61
|
+
```ts
|
|
62
|
+
// app/api/content-overlay/[...action]/route.ts
|
|
63
|
+
import { createContentAPI } from "next-content-overlay/server";
|
|
22
64
|
|
|
23
|
-
|
|
65
|
+
const handler = createContentAPI();
|
|
66
|
+
export const GET = handler;
|
|
67
|
+
export const POST = handler;
|
|
68
|
+
```
|
|
24
69
|
|
|
25
|
-
|
|
70
|
+
Or scaffold it with one command:
|
|
26
71
|
|
|
27
72
|
```bash
|
|
28
|
-
|
|
73
|
+
npx content-overlay setup
|
|
29
74
|
```
|
|
30
75
|
|
|
31
|
-
|
|
76
|
+
**That's it.** Press `Ctrl+Shift+E`, click any `<Editable>` text, edit it, save. Click **Publish Drafts** when you're ready to ship.
|
|
32
77
|
|
|
33
|
-
|
|
78
|
+
## How it works
|
|
34
79
|
|
|
35
|
-
```bash
|
|
36
|
-
npx content-overlay init
|
|
37
|
-
npx content-overlay scan
|
|
38
|
-
npx content-overlay edit app.page.your-key "Your updated text"
|
|
39
|
-
npx content-overlay publish
|
|
40
80
|
```
|
|
81
|
+
┌───────────────────────┐ ┌──────────────────────┐ ┌──────────────────────────┐
|
|
82
|
+
│ <Editable> component │ ───▶ │ createContentAPI() │ ───▶ │ content/site.json │
|
|
83
|
+
│ (click-to-edit UI) │ │ (Next.js route) │ │ .overlay-content/*.json │
|
|
84
|
+
└───────────────────────┘ └──────────────────────┘ └──────────────────────────┘
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
- **`content/site.json`** — your published content, committed to git.
|
|
88
|
+
- **`.overlay-content/draft.json`** — working drafts (per-key versioned).
|
|
89
|
+
- **`.overlay-content/history.json`** — per-key version history for restore.
|
|
90
|
+
|
|
91
|
+
All JSON. All in your repo. No database, no external service.
|
|
92
|
+
|
|
93
|
+
## Components API
|
|
94
|
+
|
|
95
|
+
### `<ContentOverlayProvider>`
|
|
96
|
+
|
|
97
|
+
| Prop | Type | Default | Description |
|
|
98
|
+
|------------------|-------------------------------|---------------------------|-------------|
|
|
99
|
+
| `initialContent` | `Record<string, string>` | `{}` | Published content map from `getContent()` for SSR hydration. |
|
|
100
|
+
| `basePath` | `string` | `"/api/content-overlay"` | Mount path for the API route. |
|
|
101
|
+
| `shortcut` | `string` | `"ctrl+shift+e"` | Keyboard shortcut to toggle edit mode. |
|
|
102
|
+
|
|
103
|
+
### `<Editable>`
|
|
104
|
+
|
|
105
|
+
| Prop | Type | Default | Description |
|
|
106
|
+
|-------------|----------------------|-------------|-------------|
|
|
107
|
+
| `k` | `string` | *(required)* | Stable content key (e.g. `"hero.title"`). |
|
|
108
|
+
| `as` | `keyof JSX.IntrinsicElements` | `"span"` | Element to render in view mode. |
|
|
109
|
+
| `children` | `ReactNode` | — | Default text used until a published value exists. |
|
|
110
|
+
| `multiline` | `boolean` | `false` | Allow newlines; uses textarea instead of single-line input. |
|
|
111
|
+
| `maxLength` | `number` | `5000` | Soft character limit. |
|
|
112
|
+
| `deletable` | `boolean` | `false` | Show a Delete button in the editor. |
|
|
113
|
+
| `className` | `string` | — | Passed through to the rendered element. |
|
|
41
114
|
|
|
42
|
-
|
|
115
|
+
### `<EditModeToggle>`
|
|
43
116
|
|
|
44
|
-
|
|
117
|
+
| Prop | Type | Default |
|
|
118
|
+
|------------|--------------------------------------------------|-----------------|
|
|
119
|
+
| `position` | `"bottom-left" \| "bottom-right" \| "top-left" \| "top-right"` | `"bottom-left"` |
|
|
120
|
+
| `className`| `string` | — |
|
|
121
|
+
|
|
122
|
+
### `useContentOverlay()`
|
|
123
|
+
|
|
124
|
+
Hook for reading edit-mode state (`isAdmin`, `isEditMode`, `pendingCount`, etc.) from custom components.
|
|
125
|
+
|
|
126
|
+
## Server API
|
|
127
|
+
|
|
128
|
+
| Export | From | Description |
|
|
129
|
+
|--------------------|--------------------------------|-------------|
|
|
130
|
+
| `createContentAPI` | `next-content-overlay/server` | Factory returning a catch-all route handler. |
|
|
131
|
+
| `getContent` | `next-content-overlay/server` | Reads `content/site.json` for SSR. |
|
|
132
|
+
| `ContentStorage` | `next-content-overlay/server` | Class wrapping the file-backed store. Useful for scripts. |
|
|
133
|
+
| `defaultAdminCheck`| `next-content-overlay/server` | The built-in admin check (dev-mode + secret cookie). |
|
|
134
|
+
|
|
135
|
+
### `createContentAPI(options?)`
|
|
136
|
+
|
|
137
|
+
```ts
|
|
138
|
+
createContentAPI({
|
|
139
|
+
isAdmin: (request) => boolean | Promise<boolean>, // Custom admin check
|
|
140
|
+
contentDir: process.cwd(), // Where to read/write files
|
|
141
|
+
revalidatePaths: ["/"], // Next.js paths to revalidate on publish
|
|
142
|
+
});
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
Sub-routes mounted under `[...action]`:
|
|
146
|
+
|
|
147
|
+
| Method | Path | Purpose |
|
|
148
|
+
|--------|-----------------------------|---------|
|
|
149
|
+
| GET | `/me` | Admin check + unpublished count |
|
|
150
|
+
| GET | `/content?keys=a,b&includeDraft=1` | Fetch published or draft values |
|
|
151
|
+
| POST | `/save` | Upsert a draft (increments version, logs history) |
|
|
152
|
+
| POST | `/publish` | Promote drafts to `content/site.json` |
|
|
153
|
+
| GET | `/history?key=hero.title` | List version history for a key |
|
|
154
|
+
| POST | `/restore` | Restore a historical version as a new draft |
|
|
155
|
+
| POST | `/login` | Validate the shared secret and set a cookie |
|
|
156
|
+
|
|
157
|
+
## Auth & admin access
|
|
158
|
+
|
|
159
|
+
Three layered defaults, pick whichever fits:
|
|
160
|
+
|
|
161
|
+
1. **No config** — you're automatically admin in `NODE_ENV === "development"`.
|
|
162
|
+
2. **`CONTENT_OVERLAY_SECRET`** env var — in production, users hit `Ctrl+Shift+E`, type the
|
|
163
|
+
secret once in a modal, and an httpOnly cookie keeps them signed in.
|
|
164
|
+
3. **Custom callback** — `createContentAPI({ isAdmin: (req) => myAuthCheck(req) })` to
|
|
165
|
+
integrate with your existing session / Supabase / Auth.js setup.
|
|
166
|
+
|
|
167
|
+
## CLI commands (secondary workflow)
|
|
168
|
+
|
|
169
|
+
The v0.1 CLI still ships and shares storage with the visual editor — so a change
|
|
170
|
+
made in one shows up in the other.
|
|
45
171
|
|
|
46
172
|
```bash
|
|
47
|
-
content-overlay init [--force]
|
|
48
|
-
content-overlay scan
|
|
49
|
-
content-overlay edit <key> <val>
|
|
50
|
-
content-overlay publish
|
|
173
|
+
content-overlay init [--force] # Create config + content files
|
|
174
|
+
content-overlay scan # Scan JSX for text strings
|
|
175
|
+
content-overlay edit <key> <val> # Update a draft value
|
|
176
|
+
content-overlay publish # Promote drafts to published content
|
|
177
|
+
content-overlay setup [--force] # Scaffold the visual-editor API route
|
|
51
178
|
content-overlay --help
|
|
52
179
|
content-overlay --version
|
|
53
180
|
```
|
|
54
181
|
|
|
55
|
-
|
|
182
|
+
Generated files:
|
|
56
183
|
|
|
57
184
|
| File | Purpose |
|
|
58
185
|
|------|---------|
|
|
59
186
|
| `content-overlay.config.json` | Scan dirs, extensions, file paths |
|
|
60
187
|
| `content/site.json` | Published content (your app reads this) |
|
|
61
188
|
| `.overlay-content/content-map.json` | Auto-generated key → source mapping |
|
|
62
|
-
| `.overlay-content/draft.json` | Working drafts
|
|
189
|
+
| `.overlay-content/draft.json` | Working drafts (versioned `DraftEntry` objects) |
|
|
190
|
+
| `.overlay-content/history.json` | Per-key version history |
|
|
63
191
|
| `.overlay-content/last-publish.json` | Publish metadata |
|
|
64
192
|
|
|
65
193
|
## 5-minute demo
|
|
@@ -69,22 +197,17 @@ A runnable Next.js demo app is included:
|
|
|
69
197
|
```bash
|
|
70
198
|
cd examples/next-demo
|
|
71
199
|
npm install
|
|
72
|
-
npm run overlay:flow
|
|
73
200
|
npm run dev
|
|
74
201
|
```
|
|
75
202
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
## How it works with AI coding
|
|
203
|
+
Open `http://localhost:3000`, press `Ctrl+Shift+E`, click the headline, edit it, save,
|
|
204
|
+
then click **Publish Drafts**. Refresh — the new text is in `content/site.json`.
|
|
79
205
|
|
|
80
|
-
|
|
206
|
+
## Migrating from v0.1
|
|
81
207
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
4. Your AI keeps building features; you keep refining copy in parallel
|
|
86
|
-
|
|
87
|
-
This separates the "build" loop from the "write" loop, so neither blocks the other.
|
|
208
|
+
See [CHANGELOG.md](CHANGELOG.md#100---plug-and-play-inline-cms) for the full migration
|
|
209
|
+
guide. The short version: the CLI keeps working, `content/site.json` is unchanged, and
|
|
210
|
+
the draft file format auto-migrates on first read (with a backup).
|
|
88
211
|
|
|
89
212
|
## Local development
|
|
90
213
|
|
|
@@ -97,9 +220,8 @@ npm run check
|
|
|
97
220
|
|
|
98
221
|
## Show your setup
|
|
99
222
|
|
|
100
|
-
If you're using `next-content-overlay` in a project, we'd love to see it in action.
|
|
101
|
-
|
|
102
|
-
Standout demos may be featured in this README.
|
|
223
|
+
If you're using `next-content-overlay` in a project, we'd love to see it in action.
|
|
224
|
+
Share a short screen capture in [Show & Tell Discussions](../../discussions/categories/show-and-tell).
|
|
103
225
|
|
|
104
226
|
## Contributing
|
|
105
227
|
|