### Run the setup wizard with npx Source: https://www.simplecommenter.com/docs/integrations/ai-agent Initializes the Simple Commenter MCP server from your project's root directory. This command starts the interactive setup wizard. ```bash npx @simple-commenter/mcp-server init ``` -------------------------------- ### Install globally and run init Source: https://www.simplecommenter.com/docs/integrations/ai-agent Alternative to npx: installs the MCP server globally, then runs the init command. Useful if you prefer a global installation. ```bash npm install -g @simple-commenter/mcp-server simple-commenter-mcp init ``` -------------------------------- ### Start an export task with start_task Source: https://www.simplecommenter.com/docs/integrations/ai-agent Use start_task to begin a long-running export or report, such as a CSV of website and asset feedback. The example shows the required arguments including project_id, source, include_archived, and an idempotency_key. Save the returned task_id and poll with get_task. ```json { "operation": "export_comments", "arguments": { "project_id": "PROJECT_ID", "source": "all", "include_archived": true }, "idempotency_key": "feedback-export-2026-09-06" } ``` -------------------------------- ### Verify setup with doctor command Source: https://www.simplecommenter.com/docs/integrations/ai-agent Checks Node.js version, config file and permissions, token, API connectivity, default project, and .mcp.json, reporting pass/fail for each. If not installed globally, use npx @simple-commenter/mcp-server doctor instead. ```bash simple-commenter-mcp doctor ``` -------------------------------- ### SimpleCommenter("boot", { user, userHash }) Source: https://www.simplecommenter.com/docs/js-api/reference Starts the widget and identifies the user in one call. This is the main entry point and is idempotent. ```APIDOC ## SimpleCommenter("boot", { user, userHash }) ### Description Starts the widget and identifies the user in one call. This is the main entry point, and it is idempotent: booting with the same user twice does nothing. On a login-protected project, boot is also what makes the widget appear at all. ### Method SimpleCommenter command ### Parameters - **user** (object) - Required - User identification object containing email, name, and optional externalId. - **email** (string) - Required - User's email address. - **name** (string) - Required - User's display name. - **externalId** (string) - Optional - Your stable user ID. - **userHash** (string) - Required - Hash for user verification (unless unverified mode is on). ### Request Example ```javascript SimpleCommenter("boot", { user: { email, name, externalId }, userHash }); ``` ### Response No response value is returned. ``` -------------------------------- ### window.simpleCommenterSettings object Source: https://www.simplecommenter.com/docs/js-api/reference Read once when the widget starts. Setting it before the script tag is equivalent to calling boot with the same values. userHash is required unless unverified mode is on. ```javascript window.simpleCommenterSettings = { user: { email: "jane@acme.com", // required for identification name: "Jane Cooper", // shown on comments externalId: "usr_123", // optional, your stable user id }, userHash: "...", // required unless unverified mode is on }; ``` -------------------------------- ### HTML Integration Example Source: https://www.simplecommenter.com/docs/installation Recommended placement of the script tag before the closing body tag of your HTML document. ```html My Website ``` -------------------------------- ### List clients on a project Source: https://www.simplecommenter.com/docs/rest-api/members-and-clients Sends a GET request to the /api/external/clients endpoint with the X-Integration-Token header and a domainId query parameter to list clients for a project. ```bash curl -H "X-Integration-Token: $TOKEN" \ "https://www.simplecommenter.com/api/external/clients?domainId=sc_xxx" ``` -------------------------------- ### Success Response Source: https://www.simplecommenter.com/docs/integrations/webhooks Example of a successful response for an integration action. ```json { "success": true, "message": "Integration action completed successfully", "result": { "_id": "507f1f77bcf86cd799439011", "oldStatus": "todo", "newStatus": "done" } } ``` -------------------------------- ### SimpleCommenter boot command Source: https://www.simplecommenter.com/docs/js-api/reference Starts the widget and identifies the user in one call. Idempotent: booting with the same user twice does nothing. On login-protected projects, boot is required for the widget to appear. ```javascript SimpleCommenter("boot", { user: { email, name, externalId }, userHash }); ``` -------------------------------- ### Manual .mcp.json configuration for Simple Commenter Source: https://www.simplecommenter.com/docs/integrations/ai-agent Merge this entry into your client's MCP configuration for a manual, portable setup. The wizard writes a node command, but this uses npx to run the server. ```json { "mcpServers": { "simple-commenter": { "command": "npx", "args": ["-y", "@simple-commenter/mcp-server", "serve"] } } } ``` -------------------------------- ### Basic Installation: Add script before closing body tag Source: https://www.simplecommenter.com/docs/installation/php Place this HTML before the closing tag. Replace sc_your_project_key with your project's public key from the Simple Commenter dashboard. The script is deferred to avoid blocking page render. ```html My PHP Site ``` -------------------------------- ### Environment-Based Configuration: Set environment variable Source: https://www.simplecommenter.com/docs/installation/php Example of setting the SIMPLE_COMMENTER_KEY environment variable in a .env file or server configuration. ```plaintext # .env or server config SIMPLE_COMMENTER_KEY=sc_your_project_key ``` -------------------------------- ### Basic Installation: Add script to base template Source: https://www.simplecommenter.com/docs/installation/flask Add the Simple Commenter script to your base template before the closing body tag. Replace 'sc_your_public_key' with your project's public key from the dashboard. ```html {% block title %}My Flask App{% endblock %} {% block content %}{% endblock %} ``` ```html {% extends "base.html" %} {% block title %}Home{% endblock %} {% block content %}

Welcome

{% endblock %} ``` -------------------------------- ### GET /comments Source: https://www.simplecommenter.com/docs/rest-api Lists comments for the account. Supports include=metadata_full to get console errors. Each comment includes a brief object if a dev brief has been written. ```APIDOC ## GET /comments ### Description Lists comments for the account. Supports include=metadata_full to get console errors. Each comment includes a brief object if a dev brief has been written. ### Method GET ### Endpoint https://www.simplecommenter.com/api/external/comments ### Query Parameters - **include** (string) - Optional - Set to `metadata_full` to include `metadata.consoleErrors` in the response. ### Authentication Header: `X-Integration-Token: YOUR_TOKEN` ### Response #### Success Response (200) Returns a list of comments. Each comment includes: - **brief** (object|null) - Present once a dev brief has been written; null before that. Contains `status`, `title`, `summary`, optional `suggestedFix`, `kind`, `confidence`, `generatedAt`. - **metadata.consoleErrorCount** (number) - Always present. - **metadata.consoleErrors** (array) - Present when `include=metadata_full`; each item has `kind`, `message`, `source`, `line`, `col`, `at`. - **text** (string) - Markdown Lite text as written. - **textFormat** (string) - Always `"markdown-lite"`. #### Error Response `{ "error": "message" }` with matching HTTP status. ``` -------------------------------- ### GET /domains Source: https://www.simplecommenter.com/docs/rest-api Lists projects (domains) in the account. Requires an integration token with read scope. ```APIDOC ## GET /domains ### Description Lists projects (domains) in the account. Requires an integration token with read scope. ### Method GET ### Endpoint https://www.simplecommenter.com/api/external/domains ### Authentication Header: `X-Integration-Token: YOUR_TOKEN` ### Response #### Success Response (200) Returns a list of domains. The exact schema is not documented in the source. #### Error Response `{ "error": "message" }` with matching HTTP status. ``` -------------------------------- ### Environment-Based Configuration: Using vlucas/phpdotenv Source: https://www.simplecommenter.com/docs/installation/php Loads environment variables using vlucas/phpdotenv and retrieves the key from $_ENV. Requires the package to be installed. ```php load(); $simpleCommenterKey = $_ENV['SIMPLE_COMMENTER_KEY'] ?? ''; ``` -------------------------------- ### Reply Action Source: https://www.simplecommenter.com/docs/integrations/webhooks Example payload for the 'reply' action. Requires 'commentId' and 'text'. ```json { "token": "your-integration-token", "action": "reply", "payload": { "commentId": "507f1f77bcf86cd799439011", "text": "Thanks for your feedback!", "name": "Support Bot", "email": "support@example.com" } } ``` -------------------------------- ### SimpleCommenter open command with event listener Source: https://www.simplecommenter.com/docs/js-api/reference Opens the comment drawer, for example from a custom 'Give feedback' button. ```javascript document .querySelector("#feedback-btn") .addEventListener("click", () => SimpleCommenter("open")); ``` -------------------------------- ### GET /api/external/clients Source: https://www.simplecommenter.com/docs/rest-api/members-and-clients Lists all clients associated with a given project domain. ```APIDOC ## GET /api/external/clients ### Description Lists all clients associated with a given project domain. ### Method GET ### Endpoint https://www.simplecommenter.com/api/external/clients ### Parameters #### Query Parameters - **domainId** (string) - Required - The project domain identifier. ### Request Example No request body required. ### Response #### Success Response (200) - **clients** (array) - List of client objects. #### Response Example No response example provided. ``` -------------------------------- ### Environment-Based Configuration: Get key from environment Source: https://www.simplecommenter.com/docs/installation/php Reads the key from the environment variable SIMPLE_COMMENTER_KEY, defaulting to an empty string if not set. Place in config.php. ```php ``` -------------------------------- ### GET /domains/{domainId}/settings Source: https://www.simplecommenter.com/docs/rest-api Retrieves settings for a specific project (domain). The domainId can be the project's public key (sc_...), project ID, or domain name. ```APIDOC ## GET /domains/{domainId}/settings ### Description Retrieves settings for a specific project (domain). The domainId can be the project's public key (sc_...), project ID, or domain name. ### Method GET ### Endpoint https://www.simplecommenter.com/api/external/domains/{domainId}/settings ### Path Parameters - **domainId** (string) - Required - The project's public key (sc_...), project ID, or domain name. ### Authentication Header: `X-Integration-Token: YOUR_TOKEN` ### Response #### Success Response (200) Returns the project settings. The exact schema is not documented in the source. #### Error Response `{ "error": "message" }` with matching HTTP status. ``` -------------------------------- ### search_comments with filters and pagination Source: https://www.simplecommenter.com/docs/integrations/ai-agent Example call to search_comments using project_ids, date range, priority, source, include_archived, limit, and offset. Use the returned next_offset to continue pagination until it is null. ```json { "project_ids": ["PROJECT_ID"], "created_after": "2026-09-01T00:00:00Z", "created_before": "2026-09-06T23:59:59Z", "priority": "high,urgent", "source": "all", "include_archived": false, "limit": 100, "offset": 0 } ``` -------------------------------- ### Status Update Action Source: https://www.simplecommenter.com/docs/integrations/webhooks Example payload for the 'status_update' action. Requires 'commentId' and at least one of 'status' or 'priority'. ```json { "token": "your-integration-token", "action": "status_update", "payload": { "commentId": "507f1f77bcf86cd799439011", "status": "done", "priority": "high" } } ``` -------------------------------- ### Brief Ready Payload Source: https://www.simplecommenter.com/docs/integrations/webhooks Sent to the New Comment webhook a few seconds after the comment, once its dev brief has been written. Only comments that get a brief trigger it; update your copy by commentId. ```APIDOC ## Brief Ready Payload ### Description Sent to the same **New Comment** webhook a few seconds after the comment, once its dev brief has been written. Only comments that get a brief trigger it; update your copy by `commentId`. ### Payload Fields - **type** (string) - Always `"comment"`. - **event** (string) - Always `"brief_ready"` for this payload. Absent on the initial comment payload. - **commentId** (string) - The unique identifier of the comment. - **commentNumber** (number) - The comment number. - **projectId** (string) - The project identifier. - **projectName** (string) - The project name. - **publicKey** (string) - The public key. - **title** (string) - The comment title. - **text** (string) - The comment text. - **status** (string) - The comment status. - **priority** (string) - The comment priority. - **date** (string) - The comment date. - **domain** (string) - The domain. - **slug** (string) - The slug. - **link** (string) - The link to the comment. - **brief** (object) - Contains `status`, `title`, `summary`, optional `suggestedFix`, `kind` (`layout` | `copy` | `link` | `visual` | `behavior` | `other`), `confidence` (`low` | `medium` | `high`), `generatedAt`, and `editedBy` / `editedAt` when a person changed it. ### Example Payload ```json { "type": "comment", "event": "brief_ready", "commentId": "507f1f77bcf86cd799439011", "commentNumber": 42, "projectId": "my-site", "projectName": "My Site", "publicKey": "sc_abc123", "title": "Bug Report", "text": "The checkout button doesn't work on mobile", "status": "todo", "priority": "normal", "date": "2024-01-15T10:30:00.000Z", "domain": "https://example.com", "slug": "/checkout", "link": "https://example.com#simple-comment=507f1f77bcf86cd799439011", "brief": { "status": "ready", "title": "Checkout button unresponsive on mobile", "summary": "The `button.checkout-submit` is covered by the sticky cart bar below 420px, so taps land on the bar.", "suggestedFix": "Add bottom padding to the checkout form equal to the bar height, or lower the bar's z-index.", "kind": "behavior", "confidence": "medium", "generatedAt": "2024-01-15T10:30:09.000Z" } } ``` ``` -------------------------------- ### Add script to index.html (Vite) Source: https://www.simplecommenter.com/docs/installation/react Edit index.html in the project root for a Vite React setup. Add the Simple Commenter script before closing body. Replace sc_your_project_key with your project's public key from the dashboard. ```html My App
``` -------------------------------- ### Python: Compute userHash with hmac Source: https://www.simplecommenter.com/docs/js-api/identity-verification Python backend example for computing the userHash HMAC-SHA256 signature. Uses the SC_PROJECT_SECRET environment variable and signs `f"{user.id}:{user.email}"`. The result is hex-encoded and lowercase. ```python import hashlib, hmac, os user_hash = hmac.new( os.environ["SC_PROJECT_SECRET"].encode(), f"{user.id}:{user.email}".encode(), hashlib.sha256, ).hexdigest() ``` -------------------------------- ### New Comment Webhook Payload Source: https://www.simplecommenter.com/docs/integrations/webhooks Example payload sent for a new comment webhook. The `type` field is always "comment" for new comments, and the same type is reused when the dev brief is written a few seconds later with `event: "brief_ready"` and a `brief` object added. The payload includes comment details, submitter info, metadata, mentions, attached users, and attachments with presigned URLs. ```json { "type": "comment", "commentId": "507f1f77bcf86cd799439011", "commentNumber": 42, "projectId": "my-site", "projectName": "My Site", "publicKey": "sc_abc123", "title": "Bug Report", "text": "The checkout button doesn't work on mobile", "textFormat": "markdown-lite", "status": "todo", "priority": "normal", "date": "2024-01-15T10:30:00.000Z", "by": "John Doe", "userData": { "name": "John Doe", "email": "john@example.com" }, "domain": "https://example.com", "slug": "/checkout", "link": "https://example.com#simple-comment=507f1f77bcf86cd799439011", "metadata": { "browser": "Chrome 120", "os": "iOS 17" }, "mentions": [], "attachedUsers": [], "attachments": [ { "type": "image", "url": "https://s3.amazonaws.com/...", "name": "Screenshot" }, { "type": "file", "url": "https://s3.amazonaws.com/...", "name": "error-log.txt" } ] } ``` -------------------------------- ### Brief Ready Payload JSON Source: https://www.simplecommenter.com/docs/integrations/webhooks Sent to the New Comment webhook a few seconds after the comment, once its dev brief has been written. Only comments that get a brief trigger it; update your copy by `commentId`. The `event` field is always `"brief_ready"` and the `brief` object contains status, title, summary, optional suggestedFix, kind, confidence, generatedAt, and editedBy/editedAt when changed. ```json { "type": "comment", "event": "brief_ready", "commentId": "507f1f77bcf86cd799439011", "commentNumber": 42, "projectId": "my-site", "projectName": "My Site", "publicKey": "sc_abc123", "title": "Bug Report", "text": "The checkout button doesn't work on mobile", "status": "todo", "priority": "normal", "date": "2024-01-15T10:30:00.000Z", "domain": "https://example.com", "slug": "/checkout", "link": "https://example.com#simple-comment=507f1f77bcf86cd799439011", "brief": { "status": "ready", "title": "Checkout button unresponsive on mobile", "summary": "The `button.checkout-submit` is covered by the sticky cart bar below 420px, so taps land on the bar.", "suggestedFix": "Add bottom padding to the checkout form equal to the bar height, or lower the bar's z-index.", "kind": "behavior", "confidence": "medium", "generatedAt": "2024-01-15T10:30:09.000Z" } } ``` -------------------------------- ### Node.js Webhook Handler for SimpleCommenter Source: https://www.simplecommenter.com/docs/integrations/webhooks Express server that listens for SimpleCommenter webhook events. Handles comment, reply, and status_update types, logging details and returning a 200 response. Use this as a starting point for receiving and processing webhook events. ```javascript const express = require("express"); const app = express(); app.use(express.json()); app.post("/webhook", (req, res) => { const { type, commentId, commentNumber } = req.body; switch (type) { case "comment": console.log(`New comment #${commentNumber}: ${req.body.text}`); // Create ticket in your system, send to Slack, etc. break; case "reply": console.log(`Reply to #${commentNumber}: ${req.body.replyText}`); break; case "status_update": console.log( `#${commentNumber} status: ${req.body.previousStatus} → ${req.body.status}`, ); break; } res.status(200).json({ received: true }); }); app.listen(3000); ``` -------------------------------- ### Configure Settings and Context Processor Source: https://www.simplecommenter.com/docs/installation/django Store the public key in settings.py and create a context processor to make the key available in templates. ```python # settings.py SIMPLE_COMMENTER_KEY = "sc_your_public_key" ``` ```python # myapp/context_processors.py from django.conf import settings def simple_commenter(request): return { 'simple_commenter_key': getattr(settings, 'SIMPLE_COMMENTER_KEY', '') } ``` ```python # settings.py TEMPLATES = [ { 'OPTIONS': { 'context_processors': [ # ... other processors 'myapp.context_processors.simple_commenter', ], }, }, ] ``` ```html {% if simple_commenter_key %} {% endif %} ``` -------------------------------- ### GET /api/external/members Source: https://www.simplecommenter.com/docs/rest-api/members-and-clients Lists all members on the account, including the account owner. Optionally, you can filter by project using the domainId query parameter to get an 'assigned' flag for each member. ```APIDOC ## GET /api/external/members ### Description Lists all members on the account, including the account owner. Optionally, you can filter by project using the domainId query parameter to get an 'assigned' flag for each member. ### Method GET ### Endpoint https://www.simplecommenter.com/api/external/members ### Parameters #### Query Parameters - **domainId** (string) - Optional - The project ID to filter members by. When provided, each member also gets an `assigned` flag indicating whether they are assigned to that project. ### Request Example ``` curl -H "X-Integration-Token: $TOKEN" \ "https://www.simplecommenter.com/api/external/members" ``` ### Response #### Success Response (200) - **members** (array) - List of member objects. #### Response Example ``` { "members": [ { "id": "string", "email": "string", "name": "string", "role": "string" } ] } ``` ``` -------------------------------- ### Create or sync a client Source: https://www.simplecommenter.com/docs/rest-api/members-and-clients Sends a POST request to create or sync a client. The request is idempotent: if the email already exists on the project, the existing client is returned and the name is updated if it changed. ```bash curl -X POST -H "X-Integration-Token: $TOKEN" \ -H "Content-Type: application/json" \ -d '{"domainId": "sc_xxx", "email": "jane@customer.com", "name": "Jane", "autoApprove": true}' \ "https://www.simplecommenter.com/api/external/clients" ``` -------------------------------- ### Boot Simple Commenter with SimpleCommenter() Source: https://www.simplecommenter.com/docs/js-api Call this to boot the widget at any time, e.g., in a SPA or after page load. Safe to call before the script loads; calls are queued and run in order. ```javascript SimpleCommenter("boot", { user: { email: "jane@acme.com", name: "Jane Cooper", externalId: "usr_123" }, userHash: hashFromYourBackend, }); ``` -------------------------------- ### Boot SimpleCommenter for selected users Source: https://www.simplecommenter.com/docs/js-api/saas-setup Call `SimpleCommenter("boot")` only for users you want to enable. The condition is yours—feature flag, plan check, admin toggle, or beta cohort—and Simple Commenter does not need to know why. Users you do not boot have no widget at all. ```javascript // After your auth state resolves: if (session.plan === "enterprise" || session.flags.includes("feedback")) { SimpleCommenter("boot", { user: { email: session.email, name: session.name, externalId: session.userId, }, userHash: session.scUserHash, }); } ``` -------------------------------- ### GET /comments/{commentId} Source: https://www.simplecommenter.com/docs/rest-api Retrieves a single comment by its ID. Always includes metadata.consoleErrors and the brief object if available. ```APIDOC ## GET /comments/{commentId} ### Description Retrieves a single comment by its ID. Always includes metadata.consoleErrors and the brief object if available. ### Method GET ### Endpoint https://www.simplecommenter.com/api/external/comments/{commentId} ### Path Parameters - **commentId** (string) - Required - The ID of the comment. ### Authentication Header: `X-Integration-Token: YOUR_TOKEN` ### Response #### Success Response (200) Returns the comment object. Includes: - **brief** (object|null) - Present once a dev brief has been written; null before that. Contains `status`, `title`, `summary`, optional `suggestedFix`, `kind`, `confidence`, `generatedAt`. - **metadata.consoleErrorCount** (number) - Always present. - **metadata.consoleErrors** (array) - Always present; each item has `kind`, `message`, `source`, `line`, `col`, `at`. - **text** (string) - Markdown Lite text as written. - **textFormat** (string) - Always `"markdown-lite"`. #### Error Response `{ "error": "message" }` with matching HTTP status. ``` -------------------------------- ### Using a Config File: Define key in config.php Source: https://www.simplecommenter.com/docs/installation/php Stores the public key in a separate config file. The key is defined as a constant SIMPLE_COMMENTER_KEY. Replace sc_your_project_key with your actual key. ```php ``` -------------------------------- ### SimpleCommenter update command Source: https://www.simplecommenter.com/docs/js-api/reference Updates attributes of the current user, for example after a display name change. Requires a hash covering the new values. ```javascript SimpleCommenter("update", { user: { email: "jane@acme.com", name: "Jane C." }, userHash: "...", }); ``` -------------------------------- ### Nuxt 3: Load script via nuxt.config.ts (Recommended) Source: https://www.simplecommenter.com/docs/installation/vue Recommended method for Nuxt 3. Add the script to the app head in nuxt.config.ts. The script is loaded with defer, and the project key is passed as a query parameter. ```javascript // nuxt.config.ts export default defineNuxtConfig({ app: { head: { script: [ { src: "https://simplecommenter.com/js/comments.min.js?id=sc_your_project_key", defer: true, }, ], }, }, }); ``` -------------------------------- ### Include Pattern: Include in pages Source: https://www.simplecommenter.com/docs/installation/php Shows how to include the reusable file in any page, placed before the closing body tag. ```html ``` -------------------------------- ### Use useSimpleCommenter composable in a component Source: https://www.simplecommenter.com/docs/installation/vue Usage example of the useSimpleCommenter composable in a Vue component. It imports the composable and calls it with your project's public key. ```vue ``` -------------------------------- ### List members with cURL Source: https://www.simplecommenter.com/docs/rest-api/members-and-clients Fetches all members. Returns { members: [...] } including the account owner. Add ?domainId=sc_xxx to include an 'assigned' flag for that project. ```bash curl -H "X-Integration-Token: $TOKEN" \ "https://www.simplecommenter.com/api/external/members" ``` -------------------------------- ### Mint a client login token Source: https://www.simplecommenter.com/docs/rest-api/members-and-clients Sends a POST request to mint a widget login token for an approved client. The token is valid for 30 days. The response contains { token, email, name }. Store the token in the visitor's browser under the 'simpleCommenterUserData' localStorage key before the widget loads, or pass it via the '?simple-commenter-token=' URL parameter. Prefer the JS API for browser login flows; use /client-token only when you need full control over token delivery. ```bash curl -X POST -H "X-Integration-Token: $TOKEN" \ -H "Content-Type: application/json" \ -d '{"domainId": "sc_xxx", "email": "jane@customer.com"}' \ "https://www.simplecommenter.com/api/external/client-token" ``` -------------------------------- ### SimpleCommenter("open") / SimpleCommenter("close") Source: https://www.simplecommenter.com/docs/js-api/reference Opens or closes the comment drawer, for example from your own "Give feedback" button. ```APIDOC ## SimpleCommenter("open") / SimpleCommenter("close") ### Description Opens or closes the comment drawer, for example from your own "Give feedback" button. ### Method SimpleCommenter command ### Parameters None. ### Request Example ```javascript document .querySelector("#feedback-btn") .addEventListener("click", () => SimpleCommenter("open")); ``` ### Response No response value is returned. ``` -------------------------------- ### Alternative Prompt (React Component) Source: https://www.simplecommenter.com/docs/installation/lovable Alternative prompt for Lovable's AI to create a React component that loads the Simple Commenter script. Replace sc_your_project_key with your project's public key. ```text Add a Simple Commenter feedback widget to my app. Create a component that loads this script: const script = document.createElement("script"); script.src = "https://simplecommenter.com/js/comments.min.js"; script.dataset.id = "sc_your_project_key"; script.defer = true; document.body.appendChild(script); Add the component to the root App.tsx file. ``` -------------------------------- ### GitHub Issue Title Format Source: https://www.simplecommenter.com/docs/integrations/github Example of the issue title format used when new feedback is synced to GitHub. The title includes the feedback ID and a short description. ```text #123 | Button not working on checkout page ``` -------------------------------- ### Add a member with cURL Source: https://www.simplecommenter.com/docs/rest-api/members-and-clients Creates a new member. role is "user" (workspace admin) or "team" (team lead). domainId is optional; when present, the member is assigned to that project. New members log in via magic link. ```bash curl -X POST -H "X-Integration-Token: $TOKEN" \ -H "Content-Type: application/json" \ -d '{"email": "dev@acme.com", "name": "Dev", "role": "team", "domainId": "sc_xxx"}' \ "https://www.simplecommenter.com/api/external/members" ``` -------------------------------- ### SimpleCommenter("update", { user, userHash }) Source: https://www.simplecommenter.com/docs/js-api/reference Updates attributes of the current user, for example after they change their display name in your app. Requires a hash covering the new values. ```APIDOC ## SimpleCommenter("update", { user, userHash }) ### Description Updates attributes of the current user, for example after they change their display name in your app. Requires a hash covering the new values. ### Method SimpleCommenter command ### Parameters - **user** (object) - Required - User object with updated attributes. - **email** (string) - Required - User's email address. - **name** (string) - Required - User's display name. - **userHash** (string) - Required - Hash covering the new values. ### Request Example ```javascript SimpleCommenter("update", { user: { email: "jane@acme.com", name: "Jane C." }, userHash: "...", }); ``` ### Response No response value is returned. ``` -------------------------------- ### Laravel: Configure services.php Source: https://www.simplecommenter.com/docs/installation/php Adds the simple_commenter key to the services configuration file, pulling from the SIMPLE_COMMENTER_KEY environment variable. ```php // config/services.php return [ 'simple_commenter' => [ 'key' => env('SIMPLE_COMMENTER_KEY'), ], ]; ``` -------------------------------- ### Next.js: Add SimpleCommenter script to root layout Source: https://www.simplecommenter.com/docs/widget/platforms Add this to your root layout or _app.js to load SimpleCommenter with lazyOnload strategy. Replace sc_your_project_key with your project's public key. ```jsx import Script from "next/script"; export default function RootLayout({ children }) { return ( {children} ``` -------------------------------- ### Include Pattern: Reusable include file Source: https://www.simplecommenter.com/docs/installation/php Creates a reusable include file that outputs the script using the key from the SIMPLE_COMMENTER_KEY constant if defined, otherwise empty. Place in includes/simple-commenter.php. ```php ``` -------------------------------- ### index.html Script Tag Source: https://www.simplecommenter.com/docs/installation/lovable Add this script tag to index.html before the closing tag. Replace sc_your_project_key with your project's public key. ```html ``` -------------------------------- ### PHP: Compute userHash with hash_hmac Source: https://www.simplecommenter.com/docs/js-api/identity-verification PHP backend example for computing the userHash HMAC-SHA256 signature. Uses the SC_PROJECT_SECRET environment variable and signs `$user->id . ':' . $user->email`. The result is hex-encoded and lowercase. ```php $userHash = hash_hmac( 'sha256', $user->id . ':' . $user->email, getenv('SC_PROJECT_SECRET') ); ``` -------------------------------- ### Conditional Loading: Show widget only on certain pages Source: https://www.simplecommenter.com/docs/installation/php Sets $show_widget to true by default, then disables it for admin pages (URI starting with /admin) and the login page (/login.php). The script is output only if $show_widget is true. ```php ``` -------------------------------- ### Environment Variables: Set config from environment Source: https://www.simplecommenter.com/docs/installation/flask Read the public key from an environment variable, with a fallback to an empty string. ```python # app.py import os app.config['SIMPLE_COMMENTER_KEY'] = os.environ.get( 'SIMPLE_COMMENTER_KEY', '' ) ``` -------------------------------- ### Ruby: Compute userHash with OpenSSL::HMAC Source: https://www.simplecommenter.com/docs/js-api/identity-verification Ruby backend example for computing the userHash HMAC-SHA256 signature. Uses the SC_PROJECT_SECRET environment variable and signs `"#{user.id}:#{user.email}"`. The result is hex-encoded and lowercase. ```ruby require "openssl" user_hash = OpenSSL::HMAC.hexdigest( "sha256", ENV["SC_PROJECT_SECRET"], "#{user.id}:#{user.email}" ) ``` -------------------------------- ### Script loading strategies Source: https://www.simplecommenter.com/docs/installation/nextjs Shows the recommended afterInteractive strategy and the lazyOnload strategy for better performance. Both load the SimpleCommenter script with the src attribute and a strategy prop. ```jsx // Recommended for most cases ```