個人 GitHub 帳號下公開儲存庫的擁有者可以登入並驗證所有權,自行管理介紹,無需管理員核准。
登入並產生驗證檔案,在 30 分鐘內將其提交至此儲存庫的預設分支。其他分支或分叉儲存庫中的檔案無效。然後在下方檢查檔案,即可無需管理員核准直接管理專案。請保留檔案以維持管理權限。
如需登入,將前往登入頁面。登入後請回到此處,再次點擊所選的驗證按鈕。
在專案資料夾中執行 /nomorevibe verify,即可驗證所有權並自行管理介紹。
一分鐘完成驗證Add live comments to any website.
翻譯準備中
取自儲存庫 README
正在載入完整 README。 以下為已儲存的摘錄。
A drop-in visual review & annotation layer for any website. Highlight text,
draw rectangles & circles, drop pins, sketch freehand and leave threaded
comments — directly on top of your live page.
By default, comments live in the visitor's own browser (localStorage) and
can be downloaded to / imported from a portable JSON file. You can also
configure your own HTTP endpoint for an explicit Send feedback action.
That single line is the whole installation.檢視完整 README ↗A drop-in visual review & annotation layer for any website. Highlight text, draw rectangles & circles, drop pins, sketch freehand and leave threaded comments — directly on top of your live page.
By default, comments live in the visitor's own browser (localStorage) and
can be downloaded to / imported from a portable JSON file. You can also
configure your own HTTP endpoint for an explicit Send feedback action.
<script src="https://cdn.jsdelivr.net/npm/@reviewjs/annotate/annotate.js" defer></script>
That single line is the whole installation.
<script> tag. No build step, no framework, no signup.| Tool | What it does |
|---|---|
| ✏️ Highlight | Select any text to highlight and comment on it |
| ▭ Rectangle | Draw a box around any region |
| ◯ Circle | Circle anything that needs attention |
| 📍 Pin | Drop a point marker anywhere |
| 〰️ Freehand | Sketch directly on the page |
| ➕ Section note | Hover any paragraph/heading for a margin comment button |
Plus: threaded replies, resolve/reopen, search & filter, deep-links to a single
comment (#an=<id>), an "off" mode that collapses to a small launcher, and a
Download / Copy / Import round-trip for sharing.
Add this just before </body>:
<script src="https://cdn.jsdelivr.net/npm/@reviewjs/annotate/annotate.js" defer></script>
That's it — reload the page and the toolbar appears in the bottom-right corner.
Pin a version for production stability:
https://cdn.jsdelivr.net/npm/@reviewjs/[email protected]/annotate.jsunpkg works too:
https://unpkg.com/@reviewjs/[email protected]/annotate.js
Download annotate.js, drop it next to your HTML and:
<script src="/annotate.js" defer></script>
Configure with data- attributes on the script tag — all optional:
<script
src="https://cdn.jsdelivr.net/npm/@reviewjs/annotate/annotate.js"
data-project="marketing-site"
data-accent="#6d28d9"
data-theme="auto"
data-position="bottom-right"
data-start-open="true"
data-note="Focus on the hero copy and pricing — flag anything off-brand."
data-spa="true"
data-post-url="https://feedback.example.com/feedback"
data-share-email="https://github.com/org/repo/issues/new?title=Review%20{page}&body={summary}"
defer
></script>
| Attribute | Default | Description |
|---|---|---|
data-project | "" | Namespace for stored comments. Keep separate sites apart. |
data-page | location.pathname | Page key comments are grouped under. |
data-accent | — | Brand color for primary buttons & the active tool. |
data-theme | auto | light, dark, or auto (sniffs your page background). |
data-position | bottom-right | bottom-right or bottom-left. |
data-blocks | sensible default | CSS selector for "section note" (+) targets. |
data-start-open | false | Set to true to show the review toolbar immediately instead of the collapsed Review pill. |
data-note | — | Author's note to reviewers — what should be reviewed. Shown when they start and atop the comments panel. |
data-spa | false | Watch pushState, replaceState, and popstate for page changes. |
data-post-url | — | URL that receives an explicit HTTP POST of the current page's export JSON. Adds Send feedback. |
data-share-email | — | Email address or URL template for Share. {page}, {count}, and {summary} become URL-encoded values for a prefilled GitHub, GitLab, Jira, or other issue URL. |
For programmatic setup, import the ES module and call init(config):
npm install @reviewjs/annotate
import Annotate from '@reviewjs/annotate';
Annotate.init({
project: 'marketing-site',
accent: '#6d28d9',
spa: true,
postUrl: '/feedback',
});
// Call Annotate.destroy() when unmounting or during hot reload.
The classic script still supports window.AnnotateConfig set before it loads.
For a script injected after page load, call window.Annotate.init(config).
init() can be called again after destroy() without leaving listeners behind.
TypeScript declarations are included in the package.
data-api)With a reviewjs backend, comments sync to a review instead of staying in the browser. The author's dashboard hands out this tag and the invite links:
<script src="https://app.reviewjs.com/annotate.js"
data-api="https://app.reviewjs.com"
data-review-id="rvw_…" defer></script>
| Attribute | Meaning |
|---|---|
data-api | The backend origin. Without it the page stays local-only, exactly as above. |
data-review-id | The review this page belongs to. |
Reviewers arrive through a personal link, https://your-site/page?an_invite=….
The token is stored for that review in the reviewer's browser and removed from
the address bar, then exchanged for a 24-hour session on every load. Only the
site addresses registered on the review may use it.
/
stub with a meta refresh, a script redirect) and drops the query string, the
token is recovered from the same-origin referrer, so the link still works.
Cross-origin referrers are never used.For a bundler, install @reviewjs/annotate, call init() after mount, and
call destroy() on unmount. Use spa: true when your router changes paths
through the History API. Dynamic content is watched and re-anchored after it
renders. The classic script remains available for static pages.
Mount it once at the app root with a useEffect:
// components/FeedbackLayer.jsx
import { useEffect } from "react";
import Annotate from "@reviewjs/annotate";
export default function FeedbackLayer() {
useEffect(() => {
Annotate.init({ project: "my-react-app", accent: "#6d28d9", spa: true });
return () => Annotate.destroy();
}, []);
return null;
}
// App.jsx
import FeedbackLayer from "./components/FeedbackLayer";
export default function App() {
return (
<>
<FeedbackLayer />
{/* your app */}
</>
);
}
Next.js (App Router): mark FeedbackLayer as a client component with
"use client"; at the top, then render it inside app/layout.jsx.
<!-- App.vue -->
<script setup>
import { onMounted, onUnmounted } from "vue";
import Annotate from "@reviewjs/annotate";
onMounted(() => {
Annotate.init({ project: "my-vue-app", accent: "#10b981", spa: true });
});
onUnmounted(() => Annotate.destroy());
</script>
For a static Vue page, the classic <script> tag also works in index.html.
Option A — no code. Install a "header/footer scripts" plugin (e.g. WPCode or Insert Headers and Footers) and paste this into the footer box:
<script src="https://cdn.jsdelivr.net/npm/@reviewjs/annotate/annotate.js" data-project="my-wp-site" defer></script>
Option B — theme code. Add to your theme's functions.php:
function reviewjs_enqueue() {
wp_enqueue_script(
'reviewjs',
'https://cdn.jsdelivr.net/npm/@reviewjs/annotate/annotate.js',
array(),
'1.5.3',
true // load in footer
);
}
add_action( 'wp_enqueue_scripts', 'reviewjs_enqueue' );
Tip: wrap the enqueue in
if ( current_user_can('edit_posts') )to show the review tools only to logged-in editors.
<!-- src/routes/+layout.svelte -->
<script>
import { onMount } from "svelte";
import Annotate from "@reviewjs/annotate";
onMount(() => {
Annotate.init({ spa: true });
return () => Annotate.destroy();
});
</script>
<slot />
In angular.json, add to the "scripts" array:
"scripts": [
"https://cdn.jsdelivr.net/npm/@reviewjs/annotate/annotate.js"
]
Paste before </body> (or into the platform's "custom code / footer" field):
<script src="https://cdn.jsdelivr.net/npm/@reviewjs/annotate/annotate.js" defer></script>
Sharing is an explicit action:
A).annotate-<page>-<date>.json file.To paste feedback directly into another tool, click Copy to copy the same complete, import-compatible JSON payload to the clipboard.
You can also drive this from code (see the API below).
Set data-post-url on the classic script or postUrl in init(config).
Reviewers will see a Send feedback button. It POSTs the same JSON export
to your endpoint with Content-Type: application/json. A successful response
must have a 2xx status. Sending does not delete the browser's local comments.
<script src="/annotate.js" data-post-url="https://feedback.example.com/feedback" defer></script>
A dependency-free Node receiver is in
examples/feedback-server.cjs. For a local
demo, run:
ALLOWED_ORIGIN=http://localhost:4200 FEEDBACK_DIR=./feedback node examples/feedback-server.cjs
It listens on port 8787 by default (PORT overrides this), accepts
POST /feedback, caps each JSON body at 1 MiB, and saves an individual JSON
file per submission. Use data-post-url="http://localhost:8787/feedback" on a
site served from http://localhost:4200. Set ALLOWED_ORIGIN to that site's
origin for cross-origin requests. Before exposing a receiver publicly, add
your site's authentication and rate limits; the example has no login.
data-share-email also accepts an issue creation URL. The values of
{page}, {count}, and {summary} are URL encoded before substitution.
For example:
<script src="/annotate.js"
data-share-email="https://github.com/org/repo/issues/new?title=Review%20{page}&body={summary}"
defer></script>
The issue link contains a short comment summary. Download or send the full JSON when teammates need to import annotations and their anchors.
A global window.Annotate is available once the classic script loads. The
ES module exports the same controller as default, plus named init and
destroy functions. The module does not start until init(config) is called.
Annotate.open(); // show the review layer and open the comments panel
Annotate.close();
Annotate.toggle();
Annotate.enable(); // show the review layer
Annotate.disable(); // collapse to the launcher
Annotate.setTool("highlight");// show the layer, then choose cursor | highlight | rect | circle | pen | pin
Annotate.comments(); // → array of comment objects for this page
Annotate.focus(id); // scroll to & highlight a comment
Annotate.export(); // trigger the JSON download
Annotate.import(); // open the file picker
await Annotate.submit(); // POST the JSON export to postUrl
Annotate.refresh(); // manually re-read the current page when spa is off
Annotate.destroy(); // remove UI, observers, and event listeners
Annotate.init({ spa: true }); // start again with programmatic settings
Annotate.clear(); // delete all comments on this page (local)
Annotate.toast("Saved!"); // show a toast
Annotate.version; // "1.5.3"
{
"id": "c…",
"page": "marketing-site:/pricing",
"url": "https://example.com/pricing",
"type": "highlight",
"author": "Jane Doe",
"text": "This price looks out of date.",
"color": "#f59e0b",
"anchor": { "exact": "…", "prefix": "…", "suffix": "…" },
"geom": null,
"resolved": false,
"replies": [],
"createdAt": "2026-06-16T10:00:00.000Z",
"updatedAt": "2026-06-16T10:00:00.000Z"
}
| Key | Action | Key | Action |
|---|---|---|---|
V | Browse | P | Pin |
H | Highlight | A | Comments panel |
R | Rectangle | O | Show / hide tools |
C | Circle | Esc | Cancel |
D | Freehand | ? | Shortcuts card |
git clone [email protected]:reviewjs/annotate.git
cd annotate
npm start # serves the demo at http://localhost:4200
Open index.html and start annotating. Framework examples live
in examples/.
Modern evergreen browsers (Chrome, Edge, Firefox, Safari). Uses standard DOM
APIs only — no polyfills required. Gracefully no-ops where localStorage is
unavailable (private mode, sandboxed iframes).
MIT — free for personal and commercial use.