@hazem3500/palette 0.9.109 → 0.9.110

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 CHANGED
@@ -17,21 +17,16 @@ Review actions update immediately while saving in the background. Failed writes
17
17
 
18
18
  ```sh
19
19
  npm install @hazem3500/palette
20
- npx @hazem3500/palette init
21
20
  ```
22
21
 
23
22
  Requires Node.js 22 or newer. The unscoped `komo` package on npm is unrelated; use `@hazem3500/palette`.
24
23
 
25
- The setup command detects your Git repository and generates `palette.config.js` before sign-in. Mount that helper in your app:
24
+ Palette has no hosted default. Comments go to a Palette server that you run, and every install sets `endpoint` to it. Start a server first:
26
25
 
27
- ```js
28
- import { initPalette } from './palette.config.js';
29
- initPalette();
30
- ```
26
+ - **Node and PostgreSQL**, including Cloud Run: run `npx @hazem3500/palette init --node` and follow the [Node self-hosting guide](./NODE.md).
27
+ - **Cloudflare Worker and D1**: run `npx @hazem3500/palette init --self-host`; see [Self-host](#self-host).
31
28
 
32
- Keep the setup terminal open and start your app in another terminal. Choose **Connect** in your app’s sidebar. Google sign-in opens in a separate window; Palette creates the project and returns you to feedback on your site. The CLI saves the final public settings to `.palette/project.json`, updates the helper, and prints an inline configuration. Use `--origin` for a different dev port or deployed site. If interrupted or expired, run `palette init` again to resume; completed projects are never overwritten.
33
-
34
- Hosted onboarding is available through the dedicated Palette service. Self-hosting is available through the same CLI.
29
+ Both print the `endpoint` and project key for your site. If your team already runs a Palette server with hosted setup turned on (`PALETTE_HOSTED=true`), connect to it with `npx @hazem3500/palette init --endpoint https://palette.example.com`; see [Hosted setup](#hosted-setup).
35
30
 
36
31
  ## Usage
37
32
 
@@ -39,13 +34,17 @@ Mount after the page has loaded:
39
34
 
40
35
  ```js
41
36
  import { initPalette } from '@hazem3500/palette';
42
- initPalette({ project: 'YOUR_PROJECT_KEY' });
37
+ initPalette({
38
+ endpoint: 'https://palette.example.com',
39
+ project: 'YOUR_PROJECT_KEY',
40
+ });
43
41
  ```
44
42
 
45
43
  Optional configuration stays at the call site:
46
44
 
47
45
  ```js
48
46
  initPalette({
47
+ endpoint: 'https://palette.example.com',
49
48
  project: 'YOUR_PROJECT_KEY',
50
49
  enabled: import.meta.env.DEV || import.meta.env.PUBLIC_PREVIEW === 'true',
51
50
  pageRoot: document.querySelector('#app'),
@@ -61,14 +60,17 @@ With React 18.2 or 19, call the hook once near your app root:
61
60
  import { usePalette } from '@hazem3500/palette/react';
62
61
 
63
62
  export function Palette() {
64
- usePalette({ project: 'YOUR_PROJECT_KEY' });
63
+ usePalette({
64
+ endpoint: 'https://palette.example.com',
65
+ project: 'YOUR_PROJECT_KEY',
66
+ });
65
67
  return null;
66
68
  }
67
69
  ```
68
70
 
69
71
  Render `<Palette />` in your app or layout. The hook handles mounting, cleanup, and React Strict Mode. Inline configuration objects are supported; unchanged values do not restart Palette. Changing configuration remounts it, and `enabled: false` removes it. Memoize callback options with `useCallback` and pass stable DOM elements for `pageRoot` or `drawerContainer`. Mount only one hook per page; do not combine it with a separate `initPalette()` call. Server rendering does not mount the tool.
70
72
 
71
- The **endpoint is the comments API**, not your website or preview URL. Hosted Palette defaults to `https://komo.offbr.co`. Google sign-in returns to `https://komo.offbr.co/auth/google/callback`, regardless of the website embedding Palette. For self-hosting, pass your Worker or Node API URL as `endpoint`. Your current page comes from the browser. Setup detects repository metadata from Git; include its printed `repo` value to enrich agent prompts.
73
+ The **endpoint is the comments API**, your Palette server, not your website or preview URL. It is required: without it, Palette logs an error and does not mount. Google sign-in returns to `ENDPOINT/auth/google/callback`, regardless of the website embedding Palette. Your current page comes from the browser. Setup detects repository metadata from Git; include its printed `repo` value to enrich agent prompts.
72
74
 
73
75
  Comments are shared across deployments by default. Use `pnpm exec palette init --branch-scope` to separate them by branch. For automatic branch detection, import from the optional generated `palette.config.js` helper and run `palette sync` before builds. It detects the current branch from deployment environment variables or Git; set `PALETTE_BRANCH` if neither is available. It fails rather than silently grouping unknown branches.
74
76
 
@@ -104,7 +106,7 @@ Palette was called komo. Existing installs keep working without changes.
104
106
  - **Crowded pins** consolidate. Comments on the same target (its persistent owner, including a custom `anchorTarget`) draw as one tight avatar stack at the oldest comment's anchor; more than three collapse to the first author and a count. Hover, keyboard focus or a tap fans the stack out in creation order, and each pin opens its own thread. Pins on different targets whose 24px targets overlap at the current zoom or Frame scale merge into a count bubble; it opens a keyboard-navigable list of those comments. Grouping never changes anchors or saves anything, the open comment's pin is always drawn at its own anchor, and a pin moved with **Move pin** stays out of stacks and bubbles. Set `pins.cluster: false` to draw every pin on its own.
105
107
  - Keyboard shortcuts: C to comment, V to browse, D to toggle Design mode, L to view all comments, H to hide or show comments, Shift+K to restore. Remap or disable them with `shortcuts`; see [Choosing shortcuts](#choosing-shortcuts). In Design mode, ? or **Keyboard shortcuts** in the empty inspector lists every canvas key and gesture.
106
108
  - Copy open feedback with selectors, source paths, page URLs, replies, and geometry into an agent.
107
- - Hosted Cloudflare storage, or your own Worker/D1 or Node/PostgreSQL service.
109
+ - Your own Worker/D1 or Node/PostgreSQL service.
108
110
 
109
111
  Comment pins stay anchored during ordinary pointer drags. Authors and verified reviewers can choose **Comment actions → Move pin** to reposition one explicitly: drag it, or use arrow keys (Shift for larger steps), then Enter or **Save position**. Escape or **Cancel move** restores its previous position without saving. Completed moves use the existing thread anchor endpoint and remain attached after reload; the page element itself never moves. Dragging a floating comment card is independent of pin placement.
110
112
 
@@ -481,7 +483,7 @@ if (import.meta.env.DEV && isShell(palette.project)) {
481
483
 
482
484
  Give a bot its own revocable credential instead of sharing your login.
483
485
 
484
- 1. **Create a token.** Signed in with Google, open **Account → API tokens** in the Palette toolbar, or `/account` on your Palette server (`https://komo.offbr.co/account` when hosted). Name the token, pick an expiry, choose scopes, and optionally limit it to projects you own or have joined. The token is shown once; copy it into your secret manager. Guest sessions cannot create tokens.
486
+ 1. **Create a token.** Signed in with Google, open **Account → API tokens** in the Palette toolbar, or `/account` on your Palette server. Name the token, pick an expiry, choose scopes, and optionally limit it to projects you own or have joined. The token is shown once; copy it into your secret manager. Guest sessions cannot create tokens.
485
487
  2. **Set `PALETTE_TOKEN`.** Export it in the bot's environment, or save it once with `printf %s "$PALETTE_TOKEN" | palette login --token` (stdin only; a token passed as an argument is refused). Check it with `palette whoami`. `palette logout` removes saved credentials.
486
488
  3. **Use the CLI as usual.** The project, endpoint, and origin come from `.palette/project.json` or the `PALETTE_*` overrides.
487
489
 
@@ -525,11 +527,13 @@ Projects default to link access. Owners can restrict feedback to invited Google
525
527
 
526
528
  ## Hosted setup
527
529
 
530
+ A Palette server with `PALETTE_HOSTED=true` lets Google users create their own workspaces. Point the CLI at it:
531
+
528
532
  ```sh
529
- pnpm exec palette init
533
+ pnpm exec palette init --endpoint https://palette.example.com
530
534
  ```
531
535
 
532
- Mount the generated `palette.config.js` helper and open your app. Select **Connect** in the sidebar and sign in with Google. Review the detected production and preview addresses in the sidebar and add any others, one per line. Connecting approves the current site and those listed addresses, including production sites that have not launched. Remove a suggested address to leave it unapproved. Google credentials and account-wide management stay on the Palette service; your site receives a session for its new project.
536
+ Mount the generated `palette.config.js` helper and open your app. Select **Connect** in the sidebar and sign in with Google. Review the detected production and preview addresses in the sidebar and add any others, one per line. Connecting approves the current site and those listed addresses, including production sites that have not launched. Remove a suggested address to leave it unapproved. Google credentials and account-wide management stay on that Palette server; your site receives a session for its new project.
533
537
 
534
538
  The CLI waits up to ten minutes and replaces the temporary setup configuration after connection. Keep the terminal open. Run `palette init` again after an interruption or expiry. The temporary polling secret stays in ignored `.palette/setup.json` and is never bundled into your site. A reload can resume commenting while the CLI finishes. Run `palette sync` before builds that use the generated helper.
535
539
 
@@ -539,7 +543,7 @@ Approve your deployed website in **Approved sites**. Palette detects deployment
539
543
 
540
544
  The setup page manages your account and approved sites. Leave comments on the website where you installed Palette.
541
545
 
542
- Return to `/setup?workspace=<project key>` to approve additional sites (up to ten). Only the Google owner can approve sites. The site address controls where that owner’s project can be embedded; it does not grant ownership of a domain or access to other projects. The API endpoint is the Palette service, not your website URL.
546
+ Return to `/setup?workspace=<project key>` to approve additional sites (up to ten). Only the Google owner can approve sites. The site address controls where that owner’s project can be embedded; it does not grant ownership of a domain or access to other projects. The API endpoint is your Palette server, not your website URL.
543
547
 
544
548
  Starter limits per owner/workspace:
545
549
 
@@ -588,11 +592,11 @@ For a Node container with PostgreSQL (including Cloud Run), use the [Node self-h
588
592
 
589
593
  Pass these to `initPalette(config)` from `@hazem3500/palette` or `usePalette(config)` from `@hazem3500/palette/react`.
590
594
 
591
- `YOUR_PROJECT_KEY` is a placeholder for a string. Hosted Palette generates the key during `palette init`; copy that value. For self-hosting, use the project identifier configured on your server. Reuse the same key across sites that should share feedback.
595
+ `YOUR_PROJECT_KEY` is a placeholder for a string. Hosted setup (`palette init --endpoint`) generates the key; copy that value. For self-hosting, use the project identifier configured on your server. Reuse the same key across sites that should share feedback.
592
596
 
593
597
  | Option | Type | Default | Purpose |
594
598
  | --- | --- | --- | --- |
595
- | `endpoint` | `string` | Hosted Palette API | Comments API root; HTTPS outside localhost. |
599
+ | `endpoint` | `string` | Required | Your Palette server's API root; HTTPS outside localhost. Without it, Palette logs an error and does not mount. |
596
600
  | `project` | `string` | Required | Public project identifier returned by setup. |
597
601
  | `repo` | `string` | Project key | Repository identifier, usually `owner/repo`. |
598
602
  | `scope` | `"project" \| "branch"` | `"project"` | `"project"` shares comments; `"branch"` separates branches. |
@@ -728,12 +732,12 @@ Limits: the image shows the element at the top of its scroll position and up to
728
732
 
729
733
  | Command / flag | Purpose |
730
734
  | --- | --- |
731
- | `palette init` | Create a Google-owned hosted workspace. |
735
+ | `palette init --endpoint URL` | Create a Google-owned workspace on a server with hosted setup turned on. |
732
736
  | `palette init --self-host` | Create your Worker and D1 database. |
733
737
  | `palette sync` | Regenerate the public client helper. Run before dev/build. |
734
738
  | `palette deploy` | Resume or redeploy generated self-host infrastructure. |
735
739
  | `--origin URL` | Optional website address. Otherwise detected from Cloudflare Pages, Vercel, or Netlify; defaults to localhost. |
736
- | `--endpoint URL` | Override hosted API or self-host deployment URL. |
740
+ | `--endpoint URL` | Your Palette server (or `PALETTE_ENDPOINT`). Required; there is no default. |
737
741
  | `--repo OWNER/REPO` | Override Git detection. |
738
742
  | `--branch-scope` | Opt into separate comments per branch. |
739
743
  | `--google-client-id ID` | Self-hosted Google OAuth client ID. |
@@ -855,7 +859,7 @@ npx @hazem3500/palette project import --file /path/to/comments.json
855
859
 
856
860
  Exports include threads, replies, reactions, element snapshots, anchors, and historical profiles across all pages and branches, including resolved feedback. They exclude sessions, credentials, verified emails, and membership. Imports use the destination repository and keep imported authors unverified. Retrying the same export is safe; existing imported records are not overwritten. Destination quotas still apply. Export retries are required if feedback changes while downloading. Keep export files private.
857
861
 
858
- Upgrade self-hosted deployments with `npm install @hazem3500/palette@latest` then `npx @hazem3500/palette deploy`; the CLI applies bundled database migrations before redeploying. Self-hosted project removal is controlled by your Worker configuration. Account-wide data requests remain available at ty@offbr.co.
862
+ Upgrade self-hosted deployments with `npm install @hazem3500/palette@latest` then `npx @hazem3500/palette deploy`; the CLI applies bundled database migrations before redeploying. Self-hosted project removal is controlled by your Worker configuration.
859
863
 
860
864
  Without `pageRoot`, a sole existing content element with a layout box enables Frame. Script and style elements do not count as content roots. Multiple roots or `display: contents` use Floating; pass a suitable existing app container for Frame.
861
865
 
package/cli/agent.mjs CHANGED
@@ -164,12 +164,13 @@ async function configuration(flags, cwd, env) {
164
164
  const project = flags.project || setting(env, "PROJECT") || settings.project;
165
165
  if (!project)
166
166
  throw Error("Run palette init in this repository, or pass --project KEY.");
167
- const endpoint = safeUrl(
168
- flags.endpoint ||
169
- setting(env, "ENDPOINT") ||
170
- settings.endpoint ||
171
- "https://komo.offbr.co"
172
- );
167
+ const configured =
168
+ flags.endpoint || setting(env, "ENDPOINT") || settings.endpoint;
169
+ if (!configured)
170
+ throw Error(
171
+ "No Palette server configured. Pass --endpoint URL, set PALETTE_ENDPOINT, or add endpoint to .palette/project.json."
172
+ );
173
+ const endpoint = safeUrl(configured);
173
174
  const origin = safeUrl(
174
175
  flags.origin ||
175
176
  setting(env, "ORIGIN") ||
package/cli/index.mjs CHANGED
@@ -5,7 +5,7 @@ import { fileURLToPath } from "node:url";
5
5
  import { spawn } from "node:child_process";
6
6
  import { createInterface } from "node:readline/promises";
7
7
  import { randomUUID, randomBytes, createHash } from "node:crypto";
8
- import { branchName, clientModule, gitValue, projectLayout, repository } from "./config.mjs";
8
+ import { branchName, clientModule, gitValue, projectLayout, repository, setting } from "./config.mjs";
9
9
 
10
10
  import { installAgentWorkflow } from "./workflow.mjs";
11
11
  import { agentCommands, agentHelp, runAgent } from "./agent.mjs";
@@ -208,8 +208,12 @@ async function init() {
208
208
  if (!selfHosted && !nodeHosted) {
209
209
  const endpoint =
210
210
  flag("--endpoint") ||
211
- (resuming ? previous.endpoint : "") ||
212
- "https://komo.offbr.co";
211
+ setting(process.env, "ENDPOINT") ||
212
+ (resuming ? previous.endpoint : "");
213
+ if (!endpoint)
214
+ throw Error(
215
+ "Palette has no default server. Pass --endpoint URL or set PALETTE_ENDPOINT to your Palette server, or self-host with palette init --node (see NODE.md) or palette init --self-host."
216
+ );
213
217
  const api = new URL(endpoint);
214
218
  if (
215
219
  api.protocol !== "https:" &&
@@ -226,7 +230,7 @@ async function init() {
226
230
  setup.expiresAt <= Date.now() ||
227
231
  flag("--origin") ||
228
232
  flag("--repo") ||
229
- flag("--endpoint")
233
+ endpoint !== previous?.endpoint
230
234
  ) {
231
235
  setup = {
232
236
  ...(await request(endpoint, "/setup/start", { repo, origins })),
@@ -381,7 +385,7 @@ async function init() {
381
385
  try {
382
386
  if (args.includes("--help") || !command)
383
387
  console.log(
384
- `Palette\n\n palette init Create a Google-owned hosted workspace\n palette init --self-host Deploy your own Worker and D1 database\n palette init --node Prepare a Node/PostgreSQL project\n palette deploy Resume self-hosted deployment\n palette sync Regenerate client settings; detect the current branch\n\nOptions: --origin URL --endpoint API_URL --repo OWNER/REPO --branch-scope\nSelf-host: --google-client-id ID; Node: --preview-origin HTTPS_WILDCARD\n\nComments are shared across deployments unless --branch-scope is set.${
388
+ `Palette\n\n palette init --endpoint API_URL Connect to an existing Palette server\n palette init --self-host Deploy your own Worker and D1 database\n palette init --node Prepare a Node/PostgreSQL project\n palette deploy Resume self-hosted deployment\n palette sync Regenerate client settings; detect the current branch\n\nOptions: --origin URL --endpoint API_URL --repo OWNER/REPO --branch-scope\nSelf-host: --google-client-id ID; Node: --preview-origin HTTPS_WILDCARD\n\nComments are shared across deployments unless --branch-scope is set.${
385
389
  agentHelp
386
390
  }`
387
391
  );